CakePHP 4.x: FriendsOfCake/crud の コアイベント と カスタムリスナー の追加方法

前提知識

Crud プラグインのコアイベント

コアイベントの利用方法

サンプル

use Crud\Action\EditAction

class UsersController extends ApiAppController
{
    public function beforeFilter(EventInterface $event)
    {
        parent::beforeFilter($event);

        $this->Crud->mapAction('edit', [
            'className' => EditAction::class,
            ],
        ]);
    }

    public function edit(?string $id = null)
    {
        // ...

        //  Crud の EventManager に 無名リスナー を登録し、
        //  Crud.beforeHandle(=Crudコアイベント)に、無名関数(=Closure) を callback としてフックする
        $this->Crud->on('beforeHandle', function (Event $event) { //第1引数: イベント名、第2引数: callback
          // callback は EventInterface を実装したクラスのインスタンスを受け取る
        });

        // 同様に Crud.beforeSave に Closure をフック
        $this->Crud->on('beforeSave', function (Event $event) {

          // Closure 内で、Crud Subject から取得可能な key は下記参照
          //  https://crud.readthedocs.io/en/latest/events.html#crud-beforesave

          // 例: Crud Subject から UserEntity を取得
          $entity = $event->getSubject()->entity;

          // ...
        });

        // 同様に Crud.afterSave に Closure をフック
        $this->Crud->on('afterSave', function (Event $event) {

          $entity = $event->getSubject()->entity;

          // ...
        });

        return $this->Crud->execute();
    }
}

カスタムイベントリスナーの追加

  • \Crud\Listener\BaseListener を継承した Listerクラスを追加し、Controller の initialize() 内で $this->Crud->addListener() する
  • ドキュメント

サンプル

use Cake\Event\EventInterface;
use Crud\Listener\BaseListener;

// カスタムイベントリスナー
class CustomListener extends BaseListener
{
    // CustomListener が処理するイベントを定義
    public function implementedEvents(): array
    {
        return [
            'Crud.beforeRender' => [
              'callable' => 'beforeRender',
              'priority' => 80, //優先順位の設定 See: https://book.cakephp.org/4/ja/core-libraries/events.html#event-priorities
            ],
        ];
    }

    // Crud.beforeRenderイベント を 受信時に実行する処理
    public function beforeRender(EventInterface $event)
    {
      // ...
    }
class ApiAppController extends Controller
{
    public function initialize(): void
    {
        $this->loadComponent('Crud.Crud', [
            'actions' => [
                'Crud.Index',
                'Crud.Add',
                'Crud.Edit',
                'Crud.View',
                'Crud.Delete',

            ]
        ]);

        $this->Crud->addListener('Crud.Api');
        $this->Crud->addListener('Crud.ApiPagination');

        // 追加
        $this->Crud->addListener('CustomListener', CustomListener::class);
    }
}