CakePHPのMigrationでMySQLのmediumtextを扱う方法
従来手動でAlter管理していたDBにCakePHPのMigrationを導入しようとした所、mediumtext/longtextを扱うのにハマったのでメモ。
MySQLのtext型は最長65,535byteの可変長文字列型ですが、UTF8換算で約2万文字となり、少し容量が足りずmediumtext(最長16MB)を使いたくなる場面があります。しかしCakePHPのMigration Pluginを使ってみると、どうもtext型のみのサポートのようでした。
以下の様なテーブルをまずは作成します。
mysql> CREATE TABLE testtable (id int, message text, medium_message mediumtext, long_message longtext);
これを元にMigrationファイルを作成します。
$ Console/cake Migrations.migration generate -f
結果作成されたMigrationファイルは
'id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'key' => 'primary'), 'message' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 'medium_message' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 'long_message' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
となり、text/mediumtext/longtextを区別せず、すべてtext型として認識されてしまいました。
これでは困るのでCakePHPのコア部分に手を入れて対応することにしました。
とはいえコアファイルを直接編集するわけではなく、CakePHPのクラスオーバーライドの仕組みを利用します。これはapp/Libにコアファイルと同名のクラスファイルを置くと、該当クラスをロードする時にコアのクラスではなく、app/Lib側のクラスに置き換えて読み込む機能です。これでCakePHPのコア自体をアプリのレポジトリに入れなくても済みます。
詳しくは以下をご覧ください。
CakePHP のクラスをオーバーライドする
実際に書き換えた部分は以下です。
元となるMySQLクラスはCakePHP 2.5.8のものです。
## project_path/app/Lib/Model/Datasource/Mysql.php // 116行付近 public $columns = array( 'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'), 'string' => array('name' => 'varchar', 'limit' => '255'), 'mediumtext' => array('name' => 'mediumtext'), 'longtext' => array('name' => 'longtext'), 'text' => array('name' => 'text'), // 777行付近 if (strpos($col, 'mediumtext') !== false) { return 'mediumtext'; } if (strpos($col, 'longtext') !== false) { return 'longtext'; } if (strpos($col, 'text') !== false) { return 'text'; }
全内容はこちら。
Gist : Mysql.php
これでmediumtext/longtextを利用することができるようになりました。
ちなみにmediumtext/longtextを公式サポートしない理由としては、CakePHPとしてはMySQLやPostgreSQL等、DBMSが変わっても同じアプリケーションコードで動くことを目指しているため、DBMSによってかき分ける必要がないようにするのが困難なため、という所だと理解しました。
参考 : LONGTEXT fields on schema generate
今回修正したコードもMySQLを使うことだけを考慮したものですので、そのあたりご理解の上参考にしていただければと思います。