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

问题描述 投票:47回答:8

我在数据库中有一个带有两个主键(id和language_id)的表,需要将其放入模型中。模型中的默认primaryKey(Laravel 5中的Model.php)是id,我希望primaryKeys将是id和id_language。我试着用数组或带','的字符串把它放进去,但是不起作用。它告诉我数组不能在String中转换。

请帮助。

谢谢!

php laravel web model composite-primary-key
8个回答
33
投票

你不能。口才不支持复合主键。

Here's a Github issue regarding this.


80
投票

我写了这个简单的PHP trait以使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');

    ...


由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);
}

更新2016-11-17

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


16
投票

似乎已经改变,因为该版本至少与Laravel 5.1兼容:

$table->primary(['key1', 'key2']);

我只是运行迁移,并且我在数据库中看到的内容与我在上面的代码中显示的内容完全一样(当然,上面的名称字段仅用于演示目的。

Update:对于迁移而言,这是正确的,但是一旦您想通过雄辩的方式插入,它就不适用于复合键,并且永远不会(最后输入):

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


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();

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

ModelName->where(['key1' => $key1, 'key2' => $key2])->update($data);

$data是您要用['attribute1' => 'value1', ..]来更新模型的数据关联数组。


[注意:您仍然可以安全地使用雄辩的关系来通过此类模型进行检索,因为它们通常用作破坏多对多关系结构的数据透视表。


0
投票

尝试查看此文档以插入与CK的多对多关系

https://laravel.com/docs/5.2/eloquent-relationships#inserting-many-to-many-relationships

编辑:一些额外的信息如您在文档中所看到的,attach和detach函数创建CK中间表中所需的链接。因此,您不必自己创建它们;)

您的情况是model->languages()->attach(language_id)


0
投票

您可以尝试使用以下模块

https://github.com/maksimru/composite-primary-keys

只需将HasCompositePrimaryKey特征添加到模型中,并指定数组值作为主键


0
投票

一个简单的解决方案,对我来说很好(Laravel 5.7):

定义其中一个 模型中的主键:

class MyTable extends Model
{
        protected $primaryKey = 'user_id';
        protected $table = 'my_table';
        protected $fillable = ['user_id', 'post_id', 'flag'];

因此,在[[Controller中传递两个主键,作为updateOrCreate方法的两个参数中的第一个,它接收两个数组:

Controller

public function post_foo(Request $request) { //PK1 is user_id, PK2 is post_id //flag - is the field that has its value changed $task = MyTable::updateOrCreate( ['user_id' => $request->header('UID'),'post_id' => $request->input('post_id')], ['user_id' => $request->header('UID'),'post_id' => $request->input('post_id'),'flag' => $request->input('flag')] ); return $task; }
说明解决方案:

您没有id列作为主键的问题仅通过Model中的一个主键解决,在DB中使用Controller中的两个主键找到了正确的行。


-3
投票
https://laravel.com/docs/5.3/migrations#columns

是,可以。

我分享我的迁移代码:

<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class RegistroEmpresa extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('registro_empresa', function(Blueprint $table) { $table->string('licencia',24); $table->string('rut',12); $table->string('nombre_empresa'); $table->string('direccion'); $table->string('comuna_Estado'); $table->string('ciudad'); $table->string('pais'); $table->string('fono'); $table->string('email'); $table->string('paginaweb'); $table->string('descripcion_tienda'); $table->string('monedauso'); $table->timestamps(); $table->primary(['licencia', 'rut']); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('registro_empresa'); } }

© www.soinside.com 2019 - 2024. All rights reserved.