終於,開始使用
Laravel
開發正式專案,雖然看過很多文章,做過一些練習,但是真搞起來,仍然是個丈二。
考慮到國情,專案一開始就考慮分庫分表的事情,資料庫管控的自增主鍵值,不利於將來搞大事,但是又不想使用 uuid
,所以要對所有表主鍵值進行統一管理,於是應用 Redis
生成.
主鍵值的填充可以在 Model
事件 creating
的時候進行,這裡有兩種方式,詳情請見下文。
1. 建立主鍵值生成器
獨立出來,在某些情況可以單獨呼叫。
<?php
namespace App\Support\Database;
use Illuminate\Support\Facades\Redis;
use Illuminate\Database\Eloquent\Model;
class PrimaryKeyValueGenerator
{
/**
* 自增值
*
* @param string $key
* @return integer
* @author Chuoke
*/
public function incrementId($key = 'model-primary-key')
{
return Redis::incr($this->formatKey($key));
}
/**
* 給模型例項生成主鍵值
*
* @param Model $model
* @return void
* @author Chuoke
*/
public function incrementIdOfModel(Model $model)
{
$key = $this->buildKeyOfModel($model);
return self::incrementId($key);
}
/**
* 給 model 例項生成一個主鍵 key
*
* @param Model $model
* @return string
* @author Chuoke
*/
public function buildKeyOfModel(Model $model)
{
return implode('_', ['table', $model->getTable(), 'id']);
}
/**
* 格式化 key
*
* @param string $key
* @return string
* @author Chuoke
*/
public function formatKey($key)
{
return strtoupper($key);
}
}
2. 主鍵填充
方便起見,把填充方法封成 trait
.
<?php
namespace App\Models\Traits;
use App\Support\Facades\PrimaryKeyValueGenerator;
trait MustFillPrimaryKey
{
/**
* 啟動填充主鍵值事件
*
* @return void
* @author Chuoke
*/
public static function bootMustFillPrimaryKeyEvent()
{
static::creating(function ($model) {
$model->fillPrimaryKey();
});
}
/**
* 填充主鍵值
*
* @param \App\Modells\Model $model
* @return void
* @author Chuoke
*/
public function fillPrimaryKey()
{
if ($this->needFillPrimaryKey()) {
$id = PrimaryKeyValueGenerator::incrementIdOfModel($this);
$this->setAttribute($this->getKeyName(), $id);
}
}
/**
* 判斷是否需要填充主鍵值
*
* @return boolean
* @author Chuoke
*/
public function needFillPrimaryKey()
{
return empty($this->getKey())
&& $this->getIncrementing()
&& $this->getKeyName() !== false;
}
}
3. 事件監聽
Model
中的 trait
可以做一個和 trait
名稱一樣的 boot
方法,如:bootbootMustFillPrimaryKey
, 這樣在啟動的時候會自動啟動,所以上面有一個這個類似的方法,只是個備份,如果是個別的需要這樣的操作,使用這種方式很方便。
我使用的是全域性事件方式.
先建立一個事件處理
<?php
namespace App\Events;
use Illuminate\Queue\SerializesModels;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
class FillPrimaryKey
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $model;
public function handle($e, $payload)
{
if (is_array($payload)) {
foreach ($payload as $model) {
$this->handle($e, $model);
}
} else if ($payload instanceof Model && \method_exists($payload, 'fillPrimaryKey')) {
$payload->fillPrimaryKey();
}
}
}
然後在 App\Providers\EventServiceProvider
中註冊監聽所有的模型建立事件.
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'eloquent.creating: *' => [
FillPrimaryKey::class,
],
];
這裡有個小坑,調了半天,回眸了若干次原始碼才發現的,就是那個 *
前面有個空格 ?
初出茅廬,一知半解,望有識之士多多指教 ?