CakePHP プレフィックスを無視してリダイレクト先を設定


背景

CakePHP開発で、未ログイン時のリダイレクト処理があり、ユーザー環境なら正しいページにリダイレクトされるが、管理画面環境だとURLが正しくならない問題が発生したので調べました。

前提その1

Authコンポーネントを利用している場合、Auth::allow() で指定したURL 以外の場合、自動的にリダイレクトする。

リダイレクト先は、Auth::loginAction の設定に準ずる。

リダイレクト処理は以下参照。
https://github.com/cakephp/cakephp/blob/2.x/lib/Cake/Controller/Component/AuthComponent.php#L366

という仕様である。
基本的に、以下の様に設定されているのが標準。

// AnyControll.php
$this->Auth->loginAction = array(
    'controller' => 'user',
    'action' => 'login'
);

前提その2

Controller::redirect()string で指定すればそのURLへリダイレクトされるが、配列で以下のように指定できる。

// string
$controller->redirect('/user/login');
=> /user/login 

// array
$controller->redirect(array('controller' => 'user', 'action' => 'login'));
=> /user/login 

通常のページの場合、結果は同じになる。

しかし、管理画面等でプレフィックスルーティング設定をしている場合、/admin 以下での挙動は以下のようになる。

// core.php
Configure::write('Routing.prefixes', array('admin'));

// string
$controller->redirect('/user/login');
=> /user/login 

// array
$controller->redirect(array('controller' => 'user', 'action' => 'login'));
=> /admin/user/login 

今回の問題はこれ。

前提その3

リダイレクトの引数から実際のURLを生成しているのは、Router::url()
https://github.com/cakephp/cakephp/blob/2.x/lib/Cake/Routing/Router.php#L829

ここで、$url が配列の場合は、プレフィックスルーティングの設定有無により、プレフィックスを動的に付ける処理が発生するため、今回のように、ログインが共通の場合は、明示指定して上げる必要がある。

解決策

この様に、prefixadmin(これはプレフィックスルーティングの設定値次第) に指定すればよい。

// core.php
Configure::write('Routing.prefixes', array('admin'));

// AnyController.php
$this->Auth->loginAction = array(
    'controller' => 'user',
    'action' => 'login',
    'prefix' => null,
    'admin' => false,
);