16

CakePHP v2.1+ で Event System を使用しようとしています

非常に強力なように見えますが、ドキュメントはやや曖昧です。イベントのトリガーは非常に簡単に思えますが、対応するリスナーを登録してイベントをリッスンする方法がわかりません。関連するセクションはここにあり、次のサンプルコードが提供されています。

App::uses('CakeEventListener', 'Event');
class UserStatistic implements CakeEventListener {

    public function implementedEvents() {
        return array(
            'Model.Order.afterPlace' => 'updateBuyStatistic',
        );
    }

    public function updateBuyStatistic($event) {
        // Code to update statistics
    }
}

// Attach the UserStatistic object to the Order's event manager
$statistics = new UserStatistic();
$this->Order->getEventManager()->attach($statistics);

ただし、このコードが存在する場所は指定されていません。特定のコントローラーの内部?アプリコントローラー内?

関連する場合、リスナーは私が書いているプラ​​グインの一部になります。

更新: これを行う一般的な方法は、プラグインの bootstrap.php ファイルにリスナー登録コードを配置することです。ただし、アプリのコントローラークラスなどが利用できないため、そこから getEventManager() を呼び出す方法がわかりません。

更新 2: リスナーはモデル内に存在できるとも言われています。

アップデート 3: ついに牽引力が!次のコードは、MyPlugin/Config/bootstrap.php 内にあるときにイベントを正常にログに記録します

App::uses('CakeEventManager', 'Event'); 
App::uses('CakeEventListener', 'Event');
class LegacyWsatListener implements CakeEventListener {

    public function implementedEvents() {
        return array(
            'Controller.Attempt.complete' => 'handleLegacyWsat',
        );
    }

    public static function handleLegacyWsat($event) { //method must be static if used by global EventManager
        // Code to update statistics
        error_log('event from bootstrap');
    }
}
 CakeEventManager::instance()->attach(array('LegacyWsatListener', 'handleLegacyWsat'), 'Controller.Attempt.complete');

理由はわかりませんが、2 つApp::uses()を 1 行に結合しようとしてもエラーになりません。

4

3 に答える 3

3

プラグインの bootstrap.php ファイル内にイベント リスナーをアタッチする場合は、回答に投稿されたヒントを使用してすべてが正常に機能するはずです。これが私のコードです(正しく動作します):

MyPlugin/Config/bootstrap.php:

App::uses('CakeEventManager', 'Event');
App::uses('MyEventListener', 'MyPlugin.Lib/Event');
CakeEventManager::instance()->attach(new MyEventListener());

MyPlugin/Lib/Event/MyEventListener.php:

App::uses('CakeEventListener', 'Event');
class MyEventListener implements CakeEventListener {
    ...
}

MyPlugin に関連するイベント リスナーは、プラグインのロード時にのみ登録されています。プラグインを使用したくない場合は、イベント リスナーを添付しません。プラグインを使用してアプリのさまざまな場所に機能を追加したい場合、これはクリーンなソリューションだと思います。

于 2013-09-26T06:21:07.983 に答える
0

コードが存在する場所は重要ではありません。実行されていることと、イベントが適切に登録および添付されていることを確認してください。

すべてのイベントが添付され、bootstrap.php からインクルードされる単一のファイルを使用しています。これにより、アプリ内のすべての場所からすべてのイベントを利用できるようになります。

コントローラー アクションなどからイベントをディスパッチすると、魔法が起こります。

$event = new CakeEvent('Model.Order.afterPlace', $this, array('some'=>'data') ));
$this->getEventManager()->dispatch($event);

ただし、EventManager にアクセスできる場所ならどこからでもイベントをディスパッチできます (デフォルトではモデル、コントローラー、およびビュー内)。

于 2013-06-04T18:16:07.250 に答える