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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31415213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:25:27  来源:igfitidea点击:

How I can put composite keys in models in Laravel 5?

phplaravelwebmodelcomposite-primary-key

提问by Sergioh Lonet

I have in my DataBase a table with two primary keys (id and language_id) and I need put it in my models. The default primaryKey in Models (Model.php in Laravel 5) is id, and I want that the primaryKeys will be id and id_language. I tried put it with arrays or a String with ',' but it doesn't work. It says me that the array could not be converted in String.

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

Please Help.

请帮忙。

Thanks!

谢谢!

采纳答案by lukasgeiter

You can't. Eloquent doesn't support composite primary keys.

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

Here's a Github issue regarding this.

这是关于此的 Github 问题。

回答by mopo922

I wrote this simple PHP traitto adapt Eloquent to handle composite keys:

我写了这个简单的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);
    }
}

Place that in a Traitsdirectory under your main model directory, then you can add a simple one-liner to the top of any composite-key model:

将其放在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);
}


Update 2016-11-17

更新 2016-11-17

I'm now maintaining this as part of an open-source package called LaravelTreats.

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

回答by sba

It seems it changed, since this one works with at least Laravel 5.1:

似乎它改变了,因为这个至少适用于 Laravel 5.1:

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

I just run the migration and what i see in the database fits to what i put in code above (of course the name fields above are just for presentation purposes).

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

Update: this is true for migrations, but as soon as you want to insert via eloquent it doesn′t work with composite keys and will never do (last entry):

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

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

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

回答by Mohyaddin Alaoddin

In migrationsyou can simply define composite primary keys for a table as @erick-suarez and @sba said, in your Schema::createor Schema::tableblock write $table->primary(['key1', 'key2']);

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

In the Eloquent modelthat represents that table you can't directly use that composite key with Eloquent methods e.g. find($key)nor save($data)but you can still retrieve the model instance for viewing purposes using

表示该表的 Eloquent 模型中,您不能直接将该组合键与 Eloquent 方法一起使用,例如,find($key)也不能save($data)使用

$modelObject = ModelName->where(['key1' => $key1, 'key2' => $key2])->first();

And if you want to update a record in that table you can use QueryBuildermethods like this:

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

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

Where $datais the data associative array you want to update your model with like so ['attribute1' => 'value1', ..].

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



Note:You can still use Eloquent relationships safely for retrieval with such models, as they are commonly used as pivot tables that break many-to-many relationship structures.

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

回答by Fellipe Sanches

An easy solution, that works well for me (Laravel 5.7):

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

Define one ofthe primary keys in the Model:

定义的一个在该主键型号

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

So pass both primary keysin the Controller, here I used in the first of the two parameters of the updateOrCreatemethod, that receives two arrays:

所以在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;
}

Explaining the solution:

解释解决方案:

The problem of you not having an idcolumn as the primary key is solved with only one primary key in Model, the correct row in DB is found with the two primary keys in the Controller.

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

回答by Maksim Martianov

you can try to use following module

您可以尝试使用以下模块

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

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

simply add HasCompositePrimaryKey trait to your model and specify array value as primary key

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

回答by Hibbem

Try looking at this documentation for inserting many to many relations with CK

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

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

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

Edit:some extra info
As you can see in the documentation, the attach and detach functions create the links needed in the CK intermediate table. So yo don't have to create them yourself ;)

编辑:一些额外信息
正如您在文档中看到的,附加和分离函数创建了 CK 中间表中所需的链接。所以你不必自己创建它们;)

In your case it would be model->languages()->attach(language_id)

在你的情况下,这将是 model->languages()->attach(language_id)

回答by Erick Suarez

https://laravel.com/docs/5.3/migrations#columns

https://laravel.com/docs/5.3/migrations#columns

Yes, u can.

是的你可以。

i share my migration code:

我分享我的迁移代码:

    <?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');
    }

}