1
1

More than 5 years have passed since last update.

October CMS プラグイン実装テク:コンポーネントからなるべく早くリダイレクトをかける

Posted at

リダイレクトするのは早いほうがいい。コンポーネントの処理が終わってからリダイレクトするのと処理前にリダイレクトするのでは、場合によってはレスポンス時間にエライ違いがでる。

TLTR

結論から言うと、コンポーネントのinitcms.page.initイベントをフックして、Redirectファサードのtoメソッドを使ってRedirectResponseオブジェクトを返してやればいい。

public function init()
{
    Event::listen('cms.page.init', function () {
        if ( $component->needRedirect() ) {
            return Redirect::to('/path/to/redirect');
        }
    });
}

詳細

通常、コンポーネントからリダイレクトするには onRunRedirectResponseオブジェクトを返す。

しかし、他にもコンポーネントがたくさん読み込まれていると最悪、多くのコンポーネントの onRun が処理されたあとにリダイレクトになる。場合によっては、無駄な処理のためにリダイレクトが遅くなる。

なので、できればコンポーネントの onRunが実行される前にリダイレクトしたい。

コンポーネントの他のタイミングと言えば init だが、このメソッドの呼び出し元である\Cms\Classes\Controller::initComponentsinitの返り値を期待していない。

どこでRedirectResponseオブジェクトを返せばリダイレクトしてもらえるか、このControllerクラスを見てみる。

コンポーネントからリダイレクトをかける話なので、最低限コンポーネントが初期化されている必要がある。ということで、コンポーネント初期化から後の処理をかいつまんで並べると下記のようになっている

  1. コンポーネント init
  2. レイアウト onInit
  3. ページ onInit
  4. cms.page.init イベント発火
  5. Ajaxハンドラ実行
  6. cms.page.start イベント発火
  7. レイアウトコンポーネント onRun
  8. ページコンポーネント onRun

ここでコンポーネントが直接絡むのがコンポーネントのinitonRunだが、イベントをフックするという手もあることがわかる。

cms.page.init イベント発火部分をみるとコメントに「カスタムレスポンスを返す機会を提供する」と書かれてる。

/**
 * @event cms.page.init
 * Provides an opportunity to return a custom response ...
 */
if ($event = $this->fireSystemEvent('cms.page.init', [$page])) {
    return $event;
}

このイベントをフックしてリダイレクトするには下記のようになる。
Redirectファサードのtoメソッドを使ってRedirectResponseオブジェクトを返してやればいい。

Event::listen('cms.page.init', function () {
    if ( $component->needRedirect() ) {
        return Redirect::to('/path/to/redirect');
    }
});

Octoberドキュメントには「イベントフックはPlugin::bootに記述するのが一般的」と書かれているが、コンポーネントのinitがイベント発火よりも前に実行されているので、コンポーネントのinitEvent::listenを記述しても問題ない。この方が、コンポーネントに実装をまとめられてきれいになる。また、このコンポーネントが使用されていないときもlistenしてしまうのを自然に避けられる。

ということで、コンポーネントのinitで下記のようにすることで、どのコンポーネントのonRunが走るよりも前に、コンポーネントの機能を使いつつ、リダイレクトをかけることができる。

public function init()
{
    Event::listen('cms.page.init', function () {
        if ( $component->needRedirect() ) {
            return Redirect::to('/path/to/redirect');
        }
    });
}

参考

イベントのドキュメント
https://octobercms.com/docs/api/cms/page/init
(すべてが載っているとは限らないので、ソースコードを検索するのをお勧めする。)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1