こんにちわ! NEKOGETです。
この記事はCodeIgniterアドベントカレンダーのために書きました! 12日目です!
https://qiita.com/advent-calendar/2017/code_igniter
この記事は、CodeIgniter3のチュートリアルをちょっと見てみようかの巻(2)の記事の補足です。
Migrationについて
本家ユーザーガイド :
https://www.codeigniter.com/user_guide/libraries/migration.html
CodeIgniterでもMigrationを使ってテーブル定義の管理をすることができます。
CodeIgniter3のチュートリアルをちょっと見てみようかの巻(2)では、チュートリアルで触れられていないため記載しませんでしたが、使うと便利です。
この機能は2の頃にはすでにあったのですがあまり知られていません。
CodeIgniterがシンプルで、たくさんの機能を実装していないという印象からではないかと思います。
設定
application/config/migration.php の編集
migrationを使用可能にして、
migrationのファイルを保存するフォルダを指定して
migrationのファイルをつくるのにtimestamp使いますを指定します。YYYYMMDDHHIISS フォーマットなので、(e.g. 20171213100537) です。
マイグレーションのバージョンは自動で最新にしといてね設定もfalseになっているのをtrueに変更です。
1 2 3 4 |
$config['migration_enabled'] = TRUE; $config['migration_path'] = APPPATH.'migrations/'; $config['migration_type'] = 'timestamp'; $config['migration_auto_latest'] = true; |
フォルダを作りましょ
1 |
mkdir application/migrations/ |
migrationファイルの作成
1 |
echo -n > application/migrations/`date '+%Y%m%d%H%M%S'`_add_news.php |
ファイルができていることを確認
1 2 3 |
$ ll application/migrations/ total 4 -rw-rw-r-- 1 ec2-user ec2-user 1047 Dec 13 11:35 20171213114048_add_news.php |
これから作るmigrationのバージョンは、 20171213114048 になりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
< ?php /** * newsテーブルを追加する * Class Migration_add_news */ class Migration_add_news extends CI_Migration { /** * migrationの実行 */ public function up() { $this->dbforge->add_field(array( 'id' => array( 'type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true ), 'title' => array( 'type' => 'VARCHAR', 'constraint' => '128', ), 'slug' => array( 'type' => 'VARCHAR', 'constraint' => '128', ), 'text' => array( 'type' => 'TEXT', 'null' => true, ), )); $this->dbforge->add_key('id', true); $this->dbforge->create_table('news'); } /** * collbackの実行 * newsテーブルのdrop */ public function down() { $this->dbforge->drop_table('news'); } } |
ユーザーガイドに従って書くとこんな感じです。
もうすでに皆様もPHP7環境だと思うのでarray()は[]にしちゃっていいと思います。
Migrate Controller Classの作成
application/controllers/Migrate.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
< ?php class Migrate extends CI_Controller { public function index() { $this->load->library('migration'); if ($this->migration->current() === FALSE) { show_error($this->migration->error_string()); } } } |
ドキュメントのサンプルコードはこんな感じで不親切です….。
application/config/migration.php の $config[‘migration_version’] = 0; のところを、実行する最終のバージョン番号を設定せねば動きません….
最新の状態にするのであれば、$this->migration->latest()を使うと良いです。
application/controllers/Migrate.php
1 2 3 4 5 6 7 8 9 10 11 12 |
class Migrate extends CI_Controller { public function index() { $this->load->library('migration'); if ($this->migration->latest() === FALSE) { show_error($this->migration->error_string()); } } } |
migrationの実行と結果/h2>
migrationを実行します。
1
php public/index.php Migrate index
1 |
php public/index.php Migrate index |
実行された結果を見てみます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 23 Server version: 5.5.57 MySQL Community Server (GPL) Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use ci3_tutorial ; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables -> ; +------------------------+ | Tables_in_ci3_tutorial | +------------------------+ | migrations | | news | +------------------------+ 2 rows in set (0.00 sec) |
newsテーブルと、migrationsテーブルができています。
1 2 3 4 5 6 7 8 9 10 |
mysql> desc news ; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(11) unsigned | NO | PRI | NULL | auto_increment | | title | varchar(128) | NO | | NULL | | | slug | varchar(128) | NO | | NULL | | | text | text | YES | | NULL | | +-------+------------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) |
1 2 3 4 5 6 7 |
mysql> select * from migrations ; +----------------+ | version | +----------------+ | 20171213114048 | +----------------+ 1 row in set (0.00 sec) |
Migrate Controllerにロールバックを追加してみる
Migrate Controllerにロールバックを追加しました。
またhttp(s)越しに、外部から叩かれないように、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class Migrate extends CI_Controller { function __construct() { parent::__construct(); //ターミナルからの実行でなければ処理しない。 if(! $this->input->is_cli_request()) { show_404(); exit; } $this->load->library('migration'); } public function index() { if ($this->migration->latest() === FALSE) { show_error($this->migration->error_string()); } } public function rollback($version) { if ($this->migration->version($version)) { echo "Migration Success.\n"; } else { show_error($this->migration->error_string()); } } } |
コマンドの実行
1 2 |
$ php public/index.php Migrate rollback 20171213114048 Migration Success. |
20171213114048_add_news.phpの状態に戻ります。
まだ1つのバージョンしかないのでこれしか指定できなかったわけですが、これもやり直したい場合ありますよね?
1 2 3 |
$ php public/index.php Migrate rollback 0 ERROR: An Error Was Encountered |
エラーを吐いてしまいますが、これでnewsテーブルがdropされます。
これはもうちょっとうまい方法が欲しい…..エラーが発生しない方法に寄せたい….ですが今日のところはこれで0地点に戻りますということにします。
やっぱりSQLで書きたいやん?
20171213114048_add_news.php の upメソッドはこんな感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * migrationの実行 */ public function up() { $this->load->database(); $sql = 'CREATE TABLE news ( id int(11) NOT NULL AUTO_INCREMENT COMMENT "id", title varchar(128) NOT NULL COMMENT "タイトル", slug varchar(128) NOT NULL COMMENT "slug", text text NOT NULL COMMENT "本文", PRIMARY KEY (id), KEY slug (slug)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT "news" ; '; $this->db->query($sql); } |
migrationはsqlそのままで行きたいかどうかは好みが別れるかと思います。
MySQLを使っての設計と実装の場合、mysqlWorkBenchを使う場合も多いでしょうし、そうするとツールからcreate table文は自動抽出でしょうし、sqlの方が便利だと思うんだよねー。
さてと、チュートリアルに戻りましょうか!!!