Laravel5でPrimaryKeyが複数で、片方がIncrementのテーブルを作るmigrationの記述方法

カテゴリー
Laravel PHP フレークワーク

目的

  • primary_keyが複数ある。
  • idはオートインクリメントにしたい。
  • LaravelのMigartionを使いたい。

と、設定されたテーブルを作りたいので…

実装

サンプルコード

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateOrderSourcesTable extends Migration
{
    const TABLE_NAME = 'examples';
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create(self::TABLE_NAME, function (Blueprint $table) {
            $table->unsignedBigInteger('id');
            $table->unsignedBigInteger('parent_id');
            $table->unsignedTinyInteger('example_data');
            $table->primary(['id', 'parent_id']);
        });
        Schema::table(self::TABLE_NAME, function (Blueprint $table) {
            // 1個目の引数がカラム名、2個目がインクリメント、3個目がunsigned flag
            $table->BigInteger('id', true, true)->change();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop(self::TABLE_NAME);
        /**
         * SEQUENCEを削除する。
         * 自動生成では {テーブル名}_{インクリメントされたカラム}_
         */
        \DB::statement('DROP SEQUENCE '.self::TABLE_NAME.'_id_seq');
    }
}

解説と重要なポイント

未検証ですが、おそらくincement()で主キーのカラムを一個作り、ALTERでもう一つカラムを追加するやり方でも出来るかもしれません。

up()

  • 先にincrement()か、primary()で主キーを一個定義してしまうと、2個目は「主キーが既にある」として、エラーになってしまいます。
 SQLSTATE[42P16]: Invalid table definition: 7
 ERROR:  multiple primary keys for table "example" are not allowed
 (SQL: alter table "example" add primary key ("secondery_id"))
  • そこで、BigInteger()でidを定義し、
    $table->primary([]);の構文で複数に主キーを指定します。
  • そして必要なカラムを後からインクリメントに変更します。
  • サンプルコードのコメントで記載してあるように、
    Integer(), BigIntegerは第2~3の引数で設定を変えられます。

drop()

  • Sequenceが残っていると rollback して再び migrate した際に、下記のようにエラーになります。
> php artisan migrate
> php artisan migrate:rollback
> php artisan migrate
 SQLSTATE[42P07]: Duplicate table: 7 ERROR:
  relation "order_examples_id_seq" already exists
 (SQL: CREATE SEQUENCE order_items_id_seq)
  • このため、dropする際はDROP SEQUENCEを直接実行しています。これは、複合キーの場合はSchema::dropしただけでは消えなかったこと、
    dropPrimary(), bigInteger()などで主キーを解除しても消えなかったためです。