投稿日:

CakePHP 2.x で Entity オブジェクトを使えるプラグイン — FkRecordModel


昨年ぐらいから CakePHP 2 を本格的に触ることになりまして、これまでの Paper ドライバーを卒業と喜んでいたんですが、いきなりつまづいた…というか不満に思ったのが Model の構造でした。CakePHP も 2 となり、もうてっきり Rails の ActiveRecord のようなものになっているかと思いきや、find メソッドが返すものは相変わらず array だったんですね。これはもう思想なのかも?…とはいえ、Paper ドライバーレベルではなかなか思想まで理解できません。同じような不満が出ていないかと検索してみたところ、次の記事が見つかりました。

同じことを思う方はいるもので♪ 早速、上のプラグインを利用させていただいたのですが、どうも CakePHP 2 系では上手く動かないようでしたので、修正を試みたものの、挫折。せっかくだからということで、自分で作ることにしました。これでも自称フレームワークマニアですしねw

その成果物がここで紹介する FkRecordModel です。GitHub に公開中です。

次のような簡単な構成になっています。

  • FkRecord        エンティティオブジェクト。find メソッドなどの戻り値などになります。
  • FkRecordCollection  findAll などの戻り値となります。
  • FkRecordModel  拡張された Model クラスです。FkRecord 生成の為に find などをオーバーライドしています。

次のような機能があります(特に高機能ではありません)。

  • FkRecord::save() で保存
  • FkRecord::validates() でバリデーション
  • FkRecordModel::build() 新しい FkRecord のビルド
  • エンティティフィールドのシンプルなアクセス。Ex. $post->title
  • Validation error は FkRecord が保持し、View で参照可能
  • HTML のラベルの表示などに利用できるフィールド別名のサポート(VerboseName)
  • リレーションを FkRecordCollection で取得。Ex. $post->tags //hasMany のデータの取得

上述の CakeEntity プラグインとの相違点は多々とあると思いますが、とりあえず大きなところで、本プラグインは「CakePHP の通常通り配列を返す」という選択肢を設けていません。find 系メソッドは常に FkRecord または FkRecordCollection を返します。(自分はたぶん使わないからです。ごめんなさい)。また、FkRecordCollection は不要だったり邪魔だと思われる方も我慢してください(イテレータにしておくと色々と便利という信条です)。ちなみに、FkRecordCollection::sort() メソッドには不満があります(削除または改良したいです。どなたか良い案ください)。

以下、簡単な利用例です。

AppModel の定義

まずは以下のように AppModel の super クラスとして本プラグインのクラスを利用します。AppModel の他に、AppRecord も作成してください。FkRecordCollection は全てのモデルで共通に利用されます。

具象モデルクラスの定義

モデルクラスでは、それぞれのモデル毎に、Model と Record を定義します。Model の定義は通常通りですが、verboseName などの指定ができます。Record にはエンティティオブジェクトで提供したい機能を実装してください。自らのフィールドへのアクセスは、$this->fieldName または $this[$alias][$fieldName] です。

Controller での利用例

Controller での利用は次のような雰囲気になります。$post->save() のようにして保存します。FkRecord::save() メソッドは、バリデーションエラーがある時には、false を返します。バリデーションエラーの内容はエンティティオブジェクトが保持し、これは View の中で利用できます。

View での利用例(一覧表示)

FkRecordModel に定義された関連は、$post->tags のようにして FkRecordCollection/FkRecord として取得できます。なお、FkRecordCollection は empty($posts) のように空判定できません。FkRecordCollection::isEmpty() メソッドを利用してください。

View での利用例(編集画面)

フォームを扱うには、FkRecord::bindFormHelper() メソッドで FormHelper をエンティティにバインドし、以後、$post->Form->text($fieldName) といった感じでフォームエレメントを出力できます。FkRecord::getVerboseName($fieldName) でフィールドの別名を取得できます。FkRecord::getError($fieldName) で、そのフィールドにエラーがあれば、その内容を取得します。

 

以上、簡単にですがご紹介まで。

もし奇特な方がいらっしゃいましたら、一度ご利用いただき、是非フィードバックなどを頂けたら嬉しいです! 是非! 是非!

 

投稿日:

CakePHP2.x の Shell で Component を使う


CakePHP2.x の Shell で Component を使う、というよくありそうな要件です。

検索してみて色々出てくるのですが、微妙に上手く行かなかったり、上手くいくものの「こっちの方が正しいのでは?」と思えたりしたので、下記にメモしておきます。

特に難しいことをしているわけでなく、ComponentCollection を new し、そこから load するのが良さそうなのかな、ということですが、ComponentCollection を自分で new するのに少々疑問もあるのです。 (; ^ω^)

もしより良い方法があればどなたかご教示ください。