5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[CakePHP3 tips] コマンドラインから複数カラムにPrimary keyを設定した際の注意点

Last updated at Posted at 2015-12-20

はじめに

皆さんがガッツリめな記事を書く中、今日は簡単なtipsの共有です!!1

CakePHPの公式ドキュメントに記載されている Bookmark tutorialを試していてハマったのですが、タイトルの通り「コマンドラインから複数カラムにPrimary keyを設定した際の注意点」を紹介します。

tl;dr

  • コマンドラインからPrimary keyに設定されたカラムにはAutoIncrementの指定が自動でつく
  • それが悪さをしてテーブル作成ができない場合があるが、実行時にエラーはでない
  • AutoIncrementの指定を削除することで正しくマイグレーションが実行できる

Cake3のマイグレーションを試してみる

チュートリアルの通りに進めていた中で、「せっかくだしSQLをそのまま実行するんじゃなくて、Migrationを使ってDBのschemaは管理しようかな」と思い試してみることにしました。

今回作成したいtableのschemaはこちら。

CREATE TABLE bookmarks_tags (
    bookmark_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (bookmark_id, tag_id),
    FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
    FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id)
);

調べると、Cake3はPhinxというライブラリを使ってMigrationの機能を提供しているようです。

ドキュメントを読んで、コマンドラインから設定できる記述はなるべく設定してマイグレーションファイルの作成を試してみます。

$ bin/cake bake migration CreateBookmarksTags bookmark_id:integer:primary tag_id:integer:primary

上記コマンドの実行で下記ファイルが作成されました。

/config/Migrations/2015********_create_bookmarks_tags.php
<?php 
use Migrations\AbstractMigration; 
 
class CreateBookmarksTags extends AbstractMigration 
{ 
 
    public $autoId = false; 
 
    public function change() 
    {   
        $table = $this->table('bookmarks_tags'); 
        $table->addColumn('bookmark_id', 'integer', [ 
            'autoIncrement' => true, 
            'default' => null, 
            'limit' => 11, 
            'null' => false, 
        ]); 
        $table->addColumn('tag_id', 'integer', [ 
            'autoIncrement' => true, 
            'default' => null, 
            'limit' => 11, 
            'null' => false, 
        ]); 
        $table->addPrimaryKey([ 
            'bookmark_id', 
            'tag_id', 
        ]); 
        $table->create(); 
    }   
}

作成したいテーブルには外部キーが設定されていますが、コマンドラインから設定することはできないようなので、その部分だけ追記して、下記の通りマイグレーションファイルを作成しました。

/config/Migrations/2015********_create_bookmarks_tags.php
<?php 
use Migrations\AbstractMigration; 
 
class CreateBookmarksTags extends AbstractMigration 
{ 
 
    public $autoId = false; 
 
    public function change() 
    {   
        $table = $this->table('bookmarks_tags'); 
        $table->addColumn('bookmark_id', 'integer', [ 
            'autoIncrement' => true, 
            'default' => null, 
            'limit' => 11, 
            'null' => false, 
        ]); 
        $table->addColumn('tag_id', 'integer', [ 
            'autoIncrement' => true, 
            'default' => null, 
            'limit' => 11, 
            'null' => false, 
        ]); 
        $table->addPrimaryKey([ 
            'bookmark_id', 
            'tag_id', 
        ]); 
        $table->addForeignKey('tag_id', 'tags', 'id');  // ← 追記
        $table->addForeignKey('bookmark_id', 'bookmarks', 'id'); // ← 追記
        $table->create(); 
    }   
}

マイグレーションを実行してもテーブルが作成されない

さて、さっそく実行してみましょう!下記コマンドで実行することができます。

$ bin/cake migrations migrate

Welcome to CakePHP v3.1.5 Console
---------------------------------------------------------------
App : src
Path: /Users/fortkle/Private/bookmarker/src/
PHP : 5.6.16
---------------------------------------------------------------
using migration path /Users/fortkle/Private/bookmarker/config/Migrations
using environment default
using adapter sqlite
using database /Users/fortkle/Private/bookmarker/database/production.sqlite

 == 20151220122251 CreateBookmarksTags: migrating
 == 20151220122251 CreateBookmarksTags: migrated 0.0036s

All Done. Took 0.0048s

もろもろ実行されて最後に「All Done」と成功を匂わせるメッセージを出しています。
本当にテーブルが作成されているか確認してみましょう(今回は楽をするためにSQLiteを使っています)。

sqlite> .tables
phinxlog

あれ?テーブルが作成されていません。「All Done」とは何だったのでしょうか...

migrationのstatusを確認します。

$ bin/cake migrations status

Welcome to CakePHP v3.1.5 Console
---------------------------------------------------------------
App : src
Path: /Users/fortkle/Private/bookmarker/src/
PHP : 5.6.16
---------------------------------------------------------------
using migration path /Users/fortkle/Private/bookmarker/config/Migrations
using environment default

 Status  Migration ID    Migration Name 
-----------------------------------------
     up  20151220122251  CreateBookmarksTags

「Status up」ということは「マイグレーション実行済み」ということでこちらも実態と異なっています...。

原因は「AUTO INCREMENT」

結論から言うと、テーブルが作成されていない理由は「AUTO INCREMENTが自動設定されていたから」でした。

コマンドラインからprimary keyを設定したカラムには自動で 'autoIncrement' => true が記述されていたため、上手くマイグレーションが実行されなかったということです。

下記の通り bookmark_id と tag_id に設定されていたautoIncrementの記述を削除してマイグレーションファイルを保存し、phinxlogから実行済みレコードを削除して再度マイグレーションすることでテーブルが作成できました。

/config/Migrations/2015********_create_bookmarks_tags.php
<?php 
use Migrations\AbstractMigration; 
 
class CreateBookmarksTags extends AbstractMigration 
{ 
 
    public $autoId = false; 
 
    public function change() 
    {   
        $table = $this->table('bookmarks_tags'); 
        $table->addColumn('bookmark_id', 'integer', [ 
            'default' => null, 
            'limit' => 11, 
            'null' => false, 
        ]); 
        $table->addColumn('tag_id', 'integer', [ 
            'default' => null, 
            'limit' => 11, 
            'null' => false, 
        ]); 
        $table->addPrimaryKey([ 
            'bookmark_id', 
            'tag_id', 
        ]); 
        $table->addForeignKey('tag_id', 'tags', 'id');
        $table->addForeignKey('bookmark_id', 'bookmarks', 'id');
        $table->create(); 
    }   
}

以上、しょーもないけどハマると結構時間が取られる系問題のtipsでした!

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?