日常工作开发中,肯定会遇到需要使用复合主键的情况,在查阅官方文档的时候,发现并不知耻
复合主键
Eloquent 要求每一个模型上至少有一个唯一标识 ID
,用他当做主键存储。模型是不支持 “复合主键” 的。无论如何,你可以添加一个多列唯一索引到你的数据表中来当做你的的唯一标识主键。
不过,数据迁移里是支持的
$table->primary(['id', 'parent_id']);//添加复合键
$table->index(['account_id', 'created_at']);//创建一个复合(或合成)索引
下面就介绍下如何实现自定义复合键吧!
首先我们创建一个Traits
文件位置:app/Models/Traits/HasCompositePrimaryKey.php
<?php
namespace App\Models\Traits;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
trait HasCompositePrimaryKey
{
/**
* 获取指示标识是否在增加的值.
*
* @return bool
*/
public function getIncrementing(): bool
{
return false;
}
/**
* 设置保存更新查询的键.
*
* @param Builder $query
* @return Builder
* @throws \Exception
*/
protected function setKeysForSaveQuery($query): Builder
{
foreach ($this->getKeyName() as $key) {
if (isset($this->$key))
$query->where($key, '=', $this->$key);
else
throw new \Exception(__METHOD__ . 'Missing part of the primary key: ' . $key);
}
return $query;
}
/**
*
* 按标识对单个记录执行查询.
*
* @param array $ids 复合主键数组 例如 [column1 => value1,column1 => value1].
* @param array $columns
* @return Builder|Model|object|null
*/
public static function find(array $ids, array $columns = ['*'])
{
$model = new self;
$query = $model->newQuery();
foreach ($model->getKeyName() as $key) {
$query->where($key, '=', $ids[$key]);
}
return $query->first($columns);
}
}
然后就是我们使用这个Traits
比如我这个Model:app/Models/MediaFavorite.php
<?php
namespace App\Models;
use App\Models\Traits\HasCompositePrimaryKey;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
class MediaFavorite extends Model
{
use HasDateTimeFormatter,HasCompositePrimaryKey;//使用我们自己的复合索引
protected $table = 'media_favorites';
public $timestamps = false;
/**
* 表的主键.
*
* @var string
*/
protected $primaryKey = ['did', 'type','data_id'];
}
这样Eloquent ORM的save()方法就可以使用了
当然,也可以使用你上面自定义的find方法
最后于 2022-1-22
被admin编辑
,原因: