ブログ

ryuzeeによるブログ記事。不定期更新

CakePHP2のbakeコマンドを拡張する方法

CakePHPの良いところの1つに、bakeコマンドでどんどん自動生成していける点があります。簡単なcrudなんかはbakeしてちょっとデザイン変えたりすれば、すぐにでも使えるレベルです。とはいえ、標準のbakeでは以下のような問題があります。

  • 標準ではcrudだけで、index()、add()、 edit()、view()、delete()しか作ってくれない
  • 何もプラグインを使わない形になっていて本当に最低限のことしかやれない
  • 例えば出力の形式もhtmlだけで、json形式での出力の出し分けとかも自分で書かないといけない
  • しかも出力されるテンプレートファイルのhtmlタグがあんまりいけてない(特にcssのクラス指定のところとか)
  • 出力されるコードのインデントやコメントの付け方が好みじゃない

毎回標準のbakeを使って生成した後に手で同じところを直すのはDRYではないので、今回は自前でbakeをカスタマイズする方法を紹介します。

方針

自前bakeの作り方ですが、絶対にlib/Cake/ 以下にあるCakePHP標準のものを直接カスタマイズしてはいけません。バージョンアップ等によって動かなくなったりする可能性があります。bakeにかぎらず、CakePHPのカスタマイズはlib以下をいじらないようにしてください。

実装

ということで、自前のbakeはプラグイン化します。今回はNewBakeという名前にします。

mkdir -p app/Plugin/NewBake/Console/Command/Task
mkdir -p app/Plugin/NewBake/Console/Templates/newbake/actions
mkdir -p app/Plugin/NewBake/Console/Templates/newbake/classes
mkdir -p app/Plugin/NewBake/Console/Templates/newbake/views

次にapp/Config/bootstrap.phpを開き、以下を追記してください。これでプラグインがロードできます。

CakePlugin::load(array('NewBake'));

次に、bakeする歳に使われるひな形のファイルをlib/Cake 以下からコピーします。

cp lib/Cake/Console/Templates/default/actions/* app/Plugin/NewBake/Console/Templates/newbake/actions
cp lib/Cake/Console/Templates/default/classes/* app/Plugin/NewBake/Console/Templates/newbake/classes
cp lib/Cake/Console/Templates/default/views/* app/Plugin/NewBake/Console/Templates/newbake/views

この時点で、bakeコマンドを叩いてモデルを作ると以下のように表示されるはずです。

./Console/cake bake
(略)
---------------------------------------------------------------
You have more than one set of templates installed.
Please choose the template set you wish to use:
---------------------------------------------------------------
1. newbake
2. default
Which bake theme would you like to use? (1/2)

ここで1を選択すれば、先ほどコピーしたフォルダにあるひな形が利用されます。 コントローラーの出力をカスタマイズする場合であれば、 Plugin/NewBake/Console/Templates/hoge/actions/controller_actions.ctp がテンプレートなので適当な記述を追加したり、変更を加えて、再度生成してみてください。変更内容が反映されたものが作成されるはずです。

同様にViewをカスタマイズしたい場合はPlugin/NewBake/Console/Templates/hoge/views以下にindex.ctpとview.ctpとform.ctp(これはaddとeditの両方で利用される)がありますので、同じようにカスタマイズすればOKです。

なお、ここまでのことでやりたいことが完了してしまう場合は、実はプラグイン化する必要はありません。 app/Console/Templates ディレクトリ以下にテンプレート名のディレクトリ( 上記の例ではnewbake)を作成し、その中に同じようにclasses、actions、viewsを用意してあげても同じことが実現できます。

応用編

自前プラグイン化

実は上記でプラグイン化したのには理由があります。 標準のbakeでは冒頭に書いたように固定のメソッド(index,add,edit,view,delete)しか出力されないのですが、例えばdownloadというメソッドを常に用意するとか、copyというメソッドを常に用意して、それにあわせたテンプレートも自動出力したい、というケースがあります。単純にコントローラーにメソッドを追加するところについては、前節で紹介したようにcontroller_actions.ctpを編集すれば良いのですが、このときテンプレートまでは一緒に作ってくれません。これは不便なので対応します。

まず、lib/Cake/Console/Command/BakeShell.php をプラグイン側にコピーし、併せてカスタマイズ対象となるタスクもコピーします。

cp ../lib/Cake/Console/Command/BakeShell.php Plugin/NewBake/Console/Command/
cp ../lib/Cake/Console/Command/Task/* Plugin/NewBake/Console/Command/Task/

このままではコピーしたBakeShellは、元々のlib側のタスクを実行してしまうので、中身を書き換えます。 変更箇所は44行目付近

/**
 * Contains tasks to load and instantiate
 *
 * @var array
 */
public $tasks = array('Project', 'DbConfig', 'Model', 'Controller', 'NewBake.View', 'Plugin', 'Fixture', 'Test');

を以下のようにタスク名の先頭にプラグイン名を追加します。

public $tasks = array(
    'NewBake.Project', 'NewBake.DbConfig', 'NewBake.Model',
    'NewBake.Controller', 'NewBake.View', 'NewBake.Plugin', 'NewBake.Fixture', 'NewBake.Test');

同様にして、Tasksディレクトリ以下にあるファイルで$tasksの指定がある箇所を全て上記と同様にプラグイン名を追加します。 以上で、新しいBakeは新しいタスクを参照するようになります。

新しいViewも自動で作るようにする

次に先ほどコピーしたPlugin/NewBake/Console/Command/Task/ViewTask.phpを編集します。 63行目付近にscaffoldingの歳にどのメソッドを作るか定義されているのでこれを拡張します。 拡張したメソッドに対応するテンプレートファイルは自分で用意して前半で紹介した場所にcopy.ctpとかdownload.ctpといった形で配置しておいてください。

/**
 * Actions to use for scaffolding
 *
 * @var array
 */
     public $scaffoldActions = array('index', 'view', 'add', 'edit', 'download', 'copy');

以上のようにすればbakeした時にこれらのテンプレートもコピーされます。 またこのままだとbakeした時に表示されるメッセージ自体は昔のままなので、217行目や428行目などのメッセージ出力部分を修正しておくとよいでしょう。

その他

完全に別のbakeになったので拡張は自由自在。新たな対話を追加したり、さらに別のファイル生成したりなんでもアリです。

アジャイルコーチングやトレーニングを提供しています

株式会社アトラクタでは、アジャイル開発に取り組むチーム向けのコーチングや、認定スクラムマスター研修などの各種トレーニングを提供しています。ぜひお気軽にご相談ください。

詳細はこちら