EC-CUBE3のプラグインのフックポイントについて

EC-CUBE Advent Calendar 2015 4日目の記事です。

4日目はEC-CUBE3でブラグインを実行する際に定義されているフックポイントについてです。

皆さんEC-CUBE3のプラグインを作っていますか?

プラグインの開発に慣れていくに従って段々と疑問に思ってくるのがフックポイントについてです。

勉強会などを行うときに必ず聞かれる内容として 「各フックポイントの実行タイミングが良く分からない」と尋ねられます。

今回は簡単に各フックポイントについてまとめました。

フックポイントを説明する前に先ずはSymfony2では標準で

  • kernel.request
  • kernel.controller
  • kernel.view
  • kernel.response
  • kernel.exception

というイベントが存在しています。

詳しくはこちら。 The HttpKernel Component (The Symfony Components)

EC-CUBE3ではSymfony2のイベント

  • kernel.request
  • kernel.response
  • kernel.terminate

の各イベントに対して処理を挟み込めるフックポイントが用意されています。

詳しくはこちら。ミドルウェア (Middlewares) | Japan Symfony Group

EC-CUBE3で用意されているフックポイントについて *1

Middleware

  • アプリケーション全体の処理の前後・特定のページの処理の前後に 処理を介入させることができます。
  • 全てのControllerに対して介入が可能です。

FilterResponseEvent

  • Responseが返却される描画される直前のHTTP HeaderやBodyを 書き換えることができます。
  • HTMLだけでなく、JSONで返却したいなどの変更も可能です。

今までの説明だけではさっぱり分からないと思いますので、実際に動作をさせてみましょう。

今回はプラグインの作成方法について説明は割愛しますが、 こういうプラグインを作って用意されているフックポイントの実行タイミングを確認してみました。

  • config.yml
name: フックポイント確認プラグイン
code: HookPoint
version: 1.0.0
event: HookPointEvent
  • event.yml
eccube.event.app.before:
  - [onAppBefore, NORMAL]
eccube.event.app.after:
  - [onAppAfter, NORMAL]
eccube.event.controller.homepage.before:
  - [onControllerBefore, NORMAL]
eccube.event.controller.homepage.after:
  - [onControllerAfter, NORMAL]
eccube.event.controller.homepage.finish:
  - [onControllerFinish, NORMAL]
eccube.event.render.homepage.before:
  - [onRenderBefore, NORMAL]
  • HookPointEvent.php
<?php
namespace Plugin\HookPoint;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class HookPointEvent
{

    /** @var  \Eccube\Application $app */
    private $app;

    public function __construct($app)
    {
        $this->app = $app;
    }

    public function onAppBefore()
    {
        error_log("onAppBefore");
    }

    public function onAppAfter()
    {
        error_log("onAppAfter");
    }

    public function onControllerBefore()
    {
        error_log("onControllerBefore");
    }

    public function onControllerAfter()
    {
        error_log("onControllerAfter");
    }

    public function onControllerFinish()
    {
        error_log("onControllerFinish");
    }

    public function onRenderBefore(FilterResponseEvent $event)
    {
        error_log("onRenderBefore");
    }
}
  • TopController.php
use Eccube\Application;

class TopController
{

    public function index(Application $app)
    {
        error_log('TopController::index')
        return $app->render('index.twig');
    }
}
  • ApplicationTrait.php(一部抜粋)
public function render($view, array $parameters = array(), Response $response = null)
{
    $twig = $this['twig'];

    if ($response instanceof StreamedResponse) {
        $response->setCallback(function () use ($twig, $view, $parameters) {
            $twig->display($view, $parameters);
        });
    } else {
        if (null === $response) {
            $response = new Response();
        }
        $response->setContent($twig->render($view, $parameters));
    }

    error_log("twig render");

    return $response;
}

これらを実行すると以下が出力されます。(実際にはもう少し出力されますが)

 onAppBefore
 onControllerBefore
 TopController::index
 twig render
 onControllerAfter
 onRenderBefore
 onAppAfter
 onControllerFinish

最初に実行されるのが

eccube.event.app.before

であとは大体想定通りと思いますが、意外だったのが

onControllerFinish

です。onAppAfterより後に実行されるのは想定外でしたが、この順番で実行されていきます。

では、それぞれのフックポイントのイベントについては何を記述すれば良いかというと、

フックポイント 処理の内容など Symfony2に対応するイベント
onAppBefore アプリケーション共通の前処理を記述 kernel.request (EARLY_EVENT)
onAppAfter アプリケーション共通の後処理を記述 kernel.request (LATE_EVENT)
onControllerBefore Controllerが実行される前に行う処理を記述 kernel.request
onControllerAfter Controllerが実行された後に行う処理を記述 kernel.response
onControllerFinish Controllerが最後まで実行された後に行う処理を記述 kernel.terminate
onRenderBefore Viewに対して項目の追加などを行う処理を記述 kernel.response

になります。

プラグインを作成していて画面の拡張や処理の拡張をする場合、どのイベントに対して記述すれば分からないときはこちらの表を参考にしてください。

この記事がフックポイントについての理解について手助けになれば幸いです。

EC-CUBEプラグインアワードの締め切りも近いので是非ご応募お待ちしております。 www.ec-cube.net

5日目は@tuyop1です。