在Laravel中定义复合主键的优雅方式

admin 2022-01-22 21:19:14 3508

日常工作开发中,肯定会遇到需要使用复合主键的情况,在查阅官方文档的时候,发现并不知耻

复合主键

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编辑 ,原因:
可爱猫?Telegram电报群 https://t.me/ikeaimao

社区声明 1、本站提供的一切软件、教程和内容信息仅限用于学习和研究目的
2、本站资源为用户分享,如有侵权请邮件与我们联系处理敬请谅解!
3、本站信息来自网络,版权争议与本站无关。您必须在下载后的24小时之内,从您的电脑或手机中彻底删除上述内容
最新回复 (0)

您可以在 登录 or 注册 后,对此帖发表评论!

返回