如何在 Laravel 5 的模型中放置复合键?

2022-08-30 09:15:29

我的数据库中有一个包含两个主键(id和language_id)的表,我需要把它放在我的模型中。模型(模型.php Laravel 5 中)中的默认 primaryKey 是 id,我希望 primaryKeys 将是 id 并id_language。我尝试用数组或字符串和',',但它不起作用。它告诉我数组无法在字符串中转换。


答案 1

我写了这个简单的PHP特征来适应Eloquent来处理复合键:

<?php

namespace App\Model\Traits; // *** Adjust this to match your model namespace! ***

use Illuminate\Database\Eloquent\Builder;

trait HasCompositePrimaryKey
{
    /**
     * Get the value indicating whether the IDs are incrementing.
     *
     * @return bool
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Set the keys for a save update query.
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function setKeysForSaveQuery(Builder $query)
    {
        foreach ($this->getKeyName() as $key) {
            // UPDATE: Added isset() per devflow's comment.
            if (isset($this->$key))
                $query->where($key, '=', $this->$key);
            else
                throw new Exception(__METHOD__ . 'Missing part of the primary key: ' . $key);
        }

        return $query;
    }

    // UPDATE: From jessedp. See his edit, below.
    /**
     * Execute a query for a single record by ID.
     *
     * @param  array  $ids Array of keys, like [column => value].
     * @param  array  $columns
     * @return mixed|static
     */
    public static function find($ids, $columns = ['*'])
    {
        $me = new self;
        $query = $me->newQuery();
        foreach ($me->getKeyName() as $key) {
            $query->where($key, '=', $ids[$key]);
        }
        return $query->first($columns);
    }
}

将其放在主模型目录下的目录中,然后您可以在任何复合键模型的顶部添加一个简单的单行代码:Traits

class MyModel extends Eloquent {
    use Traits\HasCompositePrimaryKey; // *** THIS!!! ***

    /**
     * The primary key of the table.
     * 
     * @var string
     */
    protected $primaryKey = array('key1', 'key2');

    ...


由jessdp添加:
这对我来说非常有效,直到我想使用Model::find ...所以下面是一些代码(可能会更好),可以添加到上面的 hasCompositePrimaryKey 特征中:
protected static function find($id, $columns = ['*'])
{
    $me = new self;
    $query = $me->newQuery();
    $i=0;

    foreach ($me->getKeyName() as $key) {
        $query->where($key, '=', $id[$i]);
        $i++;
    }

    return $query->first($columns);
}

更新 2016-11-17

我现在将其作为名为LaravelTreats的开源软件包的一部分进行维护。

更新 2020-06-10

LaravelTreats已经死了,但无论如何都要享受代码:)

多年来,一些深入的用例引起了我的注意,这些用例在哪里崩溃了。这应该适用于绝大多数用例,但要知道,如果你试图变得花哨,你可能不得不重新考虑你的方法。


答案 2

你不能。Eloquent 不支持复合主键。

这是一个关于此的Github问题。


推荐