web-dev-qa-db-ja.com

Laravel 5のモデルに複合キーを配置するにはどうすればよいですか?

データベースに2つのプライマリキー(idとlanguage_id)を持つテーブルがあり、モデルにそれを配置する必要があります。 ModelsのデフォルトのprimaryKey(Laravel 5のModel.php)はidであり、primaryKeysがidおよびid_languageになるようにします。配列または '、'を含む文字列で配置しようとしましたが、機能しません。配列を文字列に変換できなかったという。

助けてください。

ありがとう!

39
Sergioh Lonet

できません。 Eloquentは複合主キーをサポートしていません。

これに関するGithubの問題です。

30
lukasgeiter

私はこの単純な 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');

    ...


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 と呼ばれるオープンソースパッケージの一部として維持しています。

71
mopo922

これは少なくともLaravel 5.1で動作するため、変更されたようです。

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

移行を実行するだけで、データベースに表示される内容は、上記のコードに入力した内容に適合します(もちろん、上記の名前フィールドは表示のみを目的としています)。

Update:これは移行に当てはまりますが、雄弁を介して挿入したいとすぐに複合キーでは機能せず、実行されません(最後エントリ):

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

16
sba

移行時Schema::createまたはSchema::tableブロック書き込み$table->primary(['key1', 'key2']);で、@ erick-suarezと@sbaが言ったように、テーブルの複合主キーを簡単に定義できます。

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', ..]のようにモデルを更新するデータ連想配列です。


注:多対多のリレーションシップ構造を壊すピボットテーブルとして一般的に使用されるため、このようなモデルでの検索には、Eloquentリレーションシップを安全に使用できます。

5

以下の2つのリンクにアクセスしてください。これらのソリューションは、私の複合キーまたは複数列の主キーの問題を解決しました-

  1. 複合キーを使用したデータベースの作成

  2. 不正なオフセットタイプエラー

0
Sadidul Islam

CKとの多対多の関係を挿入するためのこのドキュメントを見てみてください

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

編集:追加情報
ドキュメンテーションでわかるように、アタッチおよびデタッチ関数は、CK中間テーブルに必要なリンクを作成します。だから、自分で作成する必要はありません;)

あなたの場合、model->languages()->attach(language_id)になります

0
Hibbem

移行ファイルは次のとおりです。移行時のキー管理の問題を解決しました。不正なオフセットタイプエラーなどが発生した場合は、後でモデルクラスを更新する必要があります。解決策はこちら- here

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAccountSessionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('account_sessions', function (Blueprint $table) {
            $table->string('session', 64);//creates a string column, that can use in primary key. don't let it exceeds 797 bytes
            $table->integer('account_id')->unsigned();//unsigned integer column
            $table->timestamps();

            $table->primary(['session', 'account_id']);//added the primary keys

            $table->foreign('account_id')->references('id')->on('accounts');//foreign key
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('account_sessions');
    }
}
0
Sadidul Islam

次のモジュールを使用してみることができます

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

hasCompositePrimaryKey特性をモデルに追加し、配列値を主キーとして指定するだけです

0

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

}
0
Erick Suarez

これが役立つことを願っています

Schema::create('vw_term_relationships', function (Blueprint $table) {
            $table->bigInteger('object_id')->unsigned()->default('0');
            $table->bigInteger('term_taxonomy_id')->unique()->unsigned()->default('0');
            $table->integer('term_order')->default('0');
            $table->primary(['object_id', 'term_taxonomy_id']);
        });

enter image description here

0
ViperTecPro