eventの追加はbeforeSaveのような概念を新しく追加しているだけなのでしょうか。
beforeSaveなどもイベントの1つなので、おっしゃる通りです。
ただ、beforeSaveなどはCakePHPのライフサイクルに組み込まれているため、自分でイベントを新たに設定するよりも使う機会は多いと思います。
どちらにせよ、指定するイベントが起こったら、特定の処理を実行したいというときに使います。
上のcheckDuplicates()で仕込んだcheck_arrの連想配列はどうゆう場合に有効利用できるのでしょうか。
分かりにくくなっている原因は、以下のようにcreateNotificationAfterCheck(Event $event, array $arr)
と書いているためかもしれません。
Eventクラスのコンストラクタに設定する第3引数の配列を$aとし、イベントを$eventとすると、createNotificationAfterCheck($event, $a[0], $a[1], $a[2], ……)
と表せます。$a
の値は$event
にも含まれているので(Event $event)
だけでも十分です。
PHP
1public function createNotificationAfterCheck(Event $event, array $arr)
2{
3}
4
PHP
1// この方が分かりやすいです
2public function createNotificationAfterCheck(Event $event)
3{
4}
5
次に'check_arr'ですが、'check_arr'は何かの判断材料に使ったり、save()する前にデータを一定の基準で変更したりするときなどに使います。
何かデータを渡さないと、できることの幅が狭くなります。
PHP
1// この方が分かりやすいです
2public function createNotificationAfterCheck(Event $event)
3{
4 // 処理の方法はCakePHPのバージョンによって違うので、適当に列挙しています
5
6 // $event->getData('check_arr')
7 // $event->setResult(['check_arr' => データ]);
8 // $event->data['check_arr']
9}
10
利用法を適当に列挙してみます。
- save()する前に、渡したデータを一定の条件で修正する
- 渡す値によって異なるログファイルにログを書き込む
- 渡す値によって異なる相手にメールを送る
- 渡す値によって異なるキャッシュファイルに書き込む
- 渡す値によってイベントを中止する
コメントに対するコメント
$this->eventManager()->dispatch($event);の部分が気になるのですが、これはEventManager.phpに$eventを通知して、atachされているeventに対して、適用するという動きでいいんでしょうか。
そうですね。新しいイベントを事前に紐づけていたリスナーに伝え、そのリスナーのメソッドを実行させるということですね。
具体的には、EventManager.phpのdispatchメソッドに$eventを渡し、そこでリスナーのメソッドに$eventを渡してそのメソッドを実行するという流れです。
createNotificationAfterCheckはpublic function createNotificationAfterCheck(Event $event , $entity , $options) {}を書かないと呼ばれないと思うのですが、beforeSaveだと「呼ばれるのはsave前だな」とフックされるタイミングが直感的にわかるのですが、独自イベントだとそのタイミングってどこで設定するんでしょうか。結局、コントローラからTableを呼ぶだけみたいになってしまうんでしょうか。
やはりイベントが発生したことをどこかで伝える必要があるので、$this->eventManager()->dispatch($event);
は必要になるのではないでしょうか。ウェブサイト表示のリクエストを受けてからデータを返すまでの流れ以外については、CakePHPではタイミングを判断しようがありません。
しかし、独自にイベントを作成した場合、そのイベントの中で処理する内容に対して独自に優先順位をつけることはできます。具体的には、$this->eventManager()->on()
で['priority' => 数値]
(デフォルトは10)を設定する方法です(バージョンによってはattach())。$this->eventManager()->on()
で同じリスナーを複数加えられるので、それらの優先順位を設定すれば、タイミングを好きに設定できます。例えば、①save()
の前に行う処理、②save()
、③save()
の後に行う処理、のように分ければbeforeSaveやafterSaveができます。
あと設計スタイルの話になりますが、呼び出すには当然、public function beforeSave(Event $event , $entity , $options) {}の記述が必要かと思いますが、それってsaveの処理を対応するコントローラに書かないといけないので、コントローラから新たにサブコントローラを呼んでみたいな細分化された設計ってできないのかなぁとちょっと思いました。
すみません、なんとなくしかやりたいことが分からないのですが、管理が面倒になるだけでサブコントローラー(サブクラス)を作ってもかまわないと思います。
それと、save()
はコントローラーだけではなく、config/bootstrap.phpでもできます。どこかで$this->eventManager()->dispatch($event);
を実行した段階で、bootstrap.phpに書いたコードがイベントのdispatchを検知して、指定したリスナー名に該当した場合に処理を行うことができます。そこではsave()
もできます。
例えば以下のように設定すると、Model.Hoge.exampleにイベントが伝わったことを検知して、function()内の処理を行います。
なお、Model.Hoge.exampleをModel.beforeSaveにすると、コントローラーにpublic function beforeSave(Event $event , $entity , $options) {}
を記述しなくてもbeforeSaveを使うことができます。
PHP
1// bootstrap.php
2use Cake\ORM\TableRegistry;
3
4$hoge = TableRegistry::get('Hoges');
5$hoge
6 ->eventManager()
7 ->on('Model.Hoge.example', ['priority' => 15], function($event, $entity) use ($hoge)
8 {
9 // バージョンによって$event->data['hoge']の取得方法が異なる
10 if($hoge->save($event->data['hoge'])) {
11 debug('save()できた!');
12 }
13 });
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/05/16 21:52 編集
2017/05/17 02:51