GiiはWebベースのコード生成ツールです。基本的な解説はガイドに詳しく載っていますので、よくわからない方はまず最初に こちら を読むことをおすすめします。今回はそのGiiを使って、コードテンプレートを自分好みにカスタマイズするところまで書いていきたいと思います。Yiiのガイドを読みつつ書いていく感じなので、ガイドとの重複が多々ありますが、予めご了承ください。
準備
Giiのコードテンプレートをカスタマイズするにあたって、まず最初にお手本となるコアのコードテンプレートを読んでいきます。例としてガイドにもあるように、モデルのコードテンプレートを参考にしたいと思います。その前に幾つかの設定を済ましておきましょう。
- データベースを作成し、
yiic webapp
でアプリケーションの雛形を生成 - protected/gii/model/templates/compact というディレクトリを作成
- protected/config/main.php で幾つかのGiiモジュールの設定を追加
- Giiを開いて、確認
- コアのコードテンプレートを 2 のディレクトリにコピーし、再度Giiで確認
3. Giiモジュールの設定を追加
1, 2は飛ばして、3から。まずGiiモジュールで幾つかの設定を追加していきます。 protected/config/main.php を開いて以下のようにします。ついでにデータベースの設定もしておいてください。
<?php
...
'modules' => array(
'gii' => array(
'class' => 'system.gii.GiiModule',
'generatorPaths' => array(
'application.gii',
),
'password' => 'tekumakumayakon',
'ipFilters' => array('127.0.0.1', '::1'),
),
),
デフォルトからの追加は generatorPaths 項目のみです。これを追加することによって protected/gii 以下のコードテンプレートも読み込んでくれるようになります。
4. Giiを開いて、確認
試しに http://localhost/hoge/index.php?r=gii/model までブラウザで移動して Code Template 項目のdefaultをクリックしてみてください。ドロップダウンでdefault以外にcompactも選択できるようになっていると思います。ただ、まだカスタマイズしたコードテンプレートを作成していない状態なので、Previewしてもエラーが表示されるかと思います。
5. コアのコードテンプレートをコピーする
次に、コアのコードテンプレートの framework/gii/generators/model/templates/default/model.php を protected/gii/model/templates/compact にコピーします。その状態で 4 でやったことを再度やってみてください。今度はエラーは表示されず、Previewでも見れるようになっているかと思います。ただ、コアのコードテンプレートのコピーなので、defaultとの違いはありません。
コアのコードテンプレートを読み解く
コードテンプレートのカスタマイズの準備は終わったので、作り方のお手本となるコアのコードテンプレートを実際眺めていきたいと思います。先ほどコピーした protected/gii/model/templates/compact/model.php を開いて実際コードを見ていきましょう。
まず最初にコメントで変数とその説明みたいなものが書いてありますね。これはガイドによると 定義済み変数 というものらしいです。実際コードを眺めていくと、いろいろな場所でこの定義済み変数が使われていることがわかります。リストは以下。
- $this: モデルのコード生成に関するさまざまな値が格納されている object型
- $tableName: テーブル名が格納されている string型
- $modelClass: モデルクラス名が格納されている string型
- $columns: テーブルの各カラムの情報などが格納されている array型
- $labels: attributeLabels()で使えそうなものが格納されている array型
- $rules: rules()で使えそうなものが格納されている array型
- $relations: relations()で使えそうなものが格納されている array型
具体的にそれぞれの変数にどのような値が格納されているのか、実際print_rなどを使って、Previewで確認するとよりわかりやすいかと思います。$labels, $rules, $ralations などの変数は attributeLabels(), rules(), relations() などのメソッド専用の変数のようで、あまり応用は利かなそうです。ので、今回は例として $columns を使って、ちょっとしたコードを追加してみます。
コードテンプレートを追加してみる
例えば、今から作るモデルがフロントエンド用のモデルだと仮定して、削除フラグが0のやつだけデータを取得できるように、あらかじめdefaultScope()に記述しておきたいとします。
<?php foreach ($columns as $column): ?>
<?php if (strpos($column->name, 'delete') !== false): ?>
/**
* @see CActiveRecord::defaultScope()
*/
public function defaultScope()
{
$alias = $this->getTableAlias(false, false);
return array(
'condition' => $alias.'.<?php echo $column->name; ?> = 0',
);
}
<?php endif; ?>
<?php endforeach; ?>
上記のように書けば、delete という文字列が含まれるカラムがあればdefaultScope()が自動で追加されて、いい感じにしてくれます(いろんな意味であまり応用が利かない感じですが、一つの例としてみてください...)。その他では、カラムのtypeがstringでsizeがnum以上ならbeforeValidate()でトリムを利かせるようにする、などいろいろ考えられます。
このように小さなことだと $columns などは利用できることがわかりましたが、例えば $rules に格納されている値そのものを変えたい場合などはどうしたらいいんでしょうか。
定義済み変数のカスタマイズ
まず、コアのGiiモジュールのディレクトリがどういう感じになっているのか見てみます。
gii/
...
generators/
...
form/
FormCode.php
FormGenerator.php
templates/
views/index.php
model/
ModelCode.php
ModelGenerator.php
templates/
views/index.php
module/
ModuleCode.php
ModuleGenerator.php
templates/
views/index.php
...
何か一連のパターンがありそうです。xxxCode.php, xxxGenerator.phpがあって、 templates, views というディレクトリがある感じです。
それぞれがどういう役割を果たしているかはYiiのガイドにも詳しく載っていますが、再度自分なりに確認してみます。
xxxCode.php
これはどのファイルも CCodeModel を継承していて、publicプロパティが各ジェネレーターのフォームと直結しているようです。また rules(), attributeLabels() などがあり、CFormModelクラスを継承したモデルを書くのとすごく似ています(実際CCodeModelはCFormModelを継承している)。また、CCodeModel のコードを見てみると rules(), attributeLabels() で予めいくつかの定義がされているので、array_mergeでマージしつつ、新たに書き足す感じになっているんですね。その他のメソッドは validate で始まるものは独自のバリデーションメソッド、generate で始まるものはコードテンプレートの定義済み変数のロジック、で最終的に prepare() メソッド内で CCodeForm をnewして、定義済み変数の値をコードテンプレートに渡したり、どのパスに生成したファイルを吐き出すかを決めているようです。
xxxGenerator.php
これはどのファイルも CCodeGenerator を継承していて $codeModel プロパティでさきほど説明した xxxCode.php のパスエイリアスを指定する形になっているようです。また、機能を付加する場合はactionから始まるメソッドを書く感じからすると、コントローラの役割と似ています(実際CCodeGeneratorはCControllerを継承している)。
templates/
これは生成されるコードテンプレートのファイルを置くディレクトリですね。
views/index.php
これは各ジェネレーターのビューそのものです。CCodeForm ウィジェットでフォームを作り、divタグでclass="tooltip"と指定してあげるとツールチップ機能が使える感じになってたりします。
各ファイルのだいたいの雰囲気からすると、GiiのModelCode, ModelGeneratorを継承したクラスを利用すれば、Giiを拡張した独自のジェネレーターが作れそうなので、さっそく作ってみます。
- /framework/gii/generators/model ディレクトリを /protected/gii/ にコピペ
- で、そのコピペしたmodelディレクトリ を myModel に、あとその下にある ModelCode.php, ModelGenerator.php をそれぞれ MyModelCode.php, MyModelGenerator.php にリネーム
- ブラウザでGiiのトップページへ移動して、MyModel Generator がリストアップされているか確認(この状態でクリックしてもファイル関連のエラーが出る)
- MyModelCode.php, MyModelGenerator.php を以下のようにする
<?php
Yii::import('system.gii.generators.model.ModelCode');
class MyModelCode extends ModelCode
{
}
<?php
Yii::import('system.gii.generators.model.ModelGenerator');
class MyModelGenerator extends ModelGenerator
{
public $codeModel='application.gii.myModel.MyModelCode';
}
あとは MyModelCode.php で、親メソッドをオーバーライドして定義済み変数のロジックを自分好みにしたり、新たに付け加えたりしながらカスタマイズしていきます。定義済み変数を追加したい場合はコアにならって generate から始まるメソッド名にしたほうがいいかもです。また、定義済み変数を追加した場合は prepare() 内で定義済み変数をビューに渡す処理をしないといけませんが、これはコアの ModelCode.php が参考になるかと思います。
最後に
今回はコアにもともとあるジェネレーターを拡張して独自のジェネレーターを作る話をしましたが、Yiiのガイドにもほとんど同じような感じで、新しいジェネレーターを作成する話が詳しく載っていますので、自分でGiiのジェネレーター作りたいって方は是非参考にしてみてください。あと、Giiを拡張したエクステンションもあったりしますので、機会があれば触ってみてください。