logo
cakephp

CakePHPにおいてモデルの各イベント間で値を共有したい場面がたまにある。
たとえば、 beforeSave でしか取得できない値を afterSave で使いたいとか、エンティティの値によって buildRules のルールに値を渡したいなど。

そういう場合、以下の方法で値の受け渡しができるようになる:

// モデル内で public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options) { $options['hogehoge'] = 'hugahuga'; } public function afterSave(Event $event, EntityInterface $entity, ArrayObject $options) { debug($options['hogehoge']); // => 'hugahuga'; }

各イベントの $options はイベント間で同じものが使いまわされているため、先に発生するイベントで追加された値は、後のイベントで利用できるようになる。
上記の例では、 beforeSave で追加した $options['hogehoge']afterSave で利用できるようになっている。

また、この $optionsルールチェッカー$rules->add の引数としても利用されているため、そこでも利用できる。

public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options) { $options['foo'] = true; } public function buildRules(RulesChecker $rules) { $rules->add(function ($entity, $options) { debug($options['foo']); // => true; }, 'ruleName'); return $rules; }

上記の例では、単純に固定値を設定しているだけだが、複数のルールで同じモデルの同じレコードを参照しないといけない場合など、あらかじめ beforeSave などで、その共通で参照しないといけないデータを取得して $options に追加しておけば、ルール毎にfindする必要がなくなり、多少は高速化が見込める。
同じコードを何度も書く必要がなくなり、見通しがよくなるはず。

idnameemail
1hogeexample.hoge@example.com
2hugaexample.huga@example.com
3piyoexample.piyo@example.com

このようなテーブル( users とする)があった時、次のコードで id を一次元配列で一発で取得できる:

$result = TableRegistry::getTableLocator()->get('Users')->find()->select('Users.id')->extract('id')->toList(); // $result = [1, 2, 3]

email だけを取得したい場合も同様:

$result = TableRegistry::getTableLocator()->get('Users')->find()->select('Users.email')->extract('email')->toList(); // $result = ['example.hoge@example.com', 'example.huga@example.com', 'example.piyo@example.com']

このコードは CakePHP3 以上であれば動くはず