如何在Laravel 5中将复合键放入模型中?

Ser*_*net 42 php model composite-primary-key web laravel

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

请帮忙.

谢谢!

mop*_*922 74

我编写了这个简单的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

    ...
Run Code Online (Sandbox Code Playgroud)


由jessedp添加:
这对我来说非常有用,直到我想使用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);
}
Run Code Online (Sandbox Code Playgroud)

更新2016-11-17

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

  • 对于那些想知道如何使用**在这里找**的人:如果你的主要对是'['A','B']`那么你找到你的条目`Model :: find(['A'=>'first_part_of_your_key ','B'=>'second_part_of_your_key'])`.复制和粘贴脚本也包含自定义方法中的错误**find**第一个参数应该是`$ id`而不是`$ ids`. (2认同)

luk*_*ter 32

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

这是关于这个问题的Github问题.

  • 我一次又一次地回到这个答案,希望Eloquent能获得复合关键支持.该问题已被锁定.谁可以成为谈论雄辩的合适人选?通过src有点太多了,我喜欢先行并理解为什么复合支持很难获得. (10认同)
  • @HonestObjections它们可用于迁移,并且已有多个版本.那不是问题.Eloquent仍然不支持复合键(出于某种原因). (5认同)
  • 不知道什么时候添加它,但它们在Laravel 5.6+中可用(https://laravel.com/docs/5.6/migrations#creating-indexes) (3认同)

sba*_*sba 16

它似乎发生了变化,因为这个至少与Laravel 5.1一起使用:

$table->primary(['key1', 'key2']);
Run Code Online (Sandbox Code Playgroud)

我只是运行迁移,我在数据库中看到的内容符合我在上面的代码中放置的内容(当然上面的名称字段仅用于演示目的).

更新:这对于迁移是正确的,但是只要您想通过eloquent插入它就不能使用复合键,并且永远不会(最后一个条目):

https://github.com/laravel/framework/issues/5517


Moh*_*din 7

在迁移中,您可以简单地为表定义复合主键,如@ erick-suarez和@sba所说,在您的Schema::createSchema::table块写入$table->primary(['key1', 'key2']);

表示该表的Eloquent模型中,您不能直接将该复合键与Eloquent方法一起使用,例如find($key),save($data)但您仍然可以检索模型实例以供查看使用

$modelObject = ModelName->where(['key1' => $key1, 'key2' => $key2])->first();
Run Code Online (Sandbox Code Playgroud)

如果要更新该表中的记录,可以使用以下QueryBuilder方法:

ModelName->where(['key1' => $key1, 'key2' => $key2])->update($data);
Run Code Online (Sandbox Code Playgroud)

$data您想要更新模型的数据关联数组在哪里['attribute1' => 'value1', ..].


注意:您仍然可以安全地使用Eloquent关系来检索此类模型,因为它们通常用作打破多对多关系结构的数据透视表.