[CakePHP]Authで2種類のユーザー認証を設定する方法

[CakePHP1.3.11]

今回は、Webサービスによくよくあるパターンである、サイト管理者向けページと、ユーザーページ(いわゆるマイページというやつ)2つの専用ページを持つサイトにおける、Auth設定方法を書いておきます。対象は、CakePHP1.3ですが、2.xでもほぼ同様のコードで動作します。

なお、この記事では、サイト管理者ページ名を、admin、マイページをmemberとして進めていきます。認証方法は、admin:Basic認証、member:ログイン画面にてメールアドレスとパスワードの認証とします。

まず、config/core.phpの、prefix設定のところを、以下のようにします。

[php]
Configure::write(‘Routing.prefixes’, array(‘admin’, ‘member’));
[/php]

そして、app_controller.phpで以下のように設定します。

[php]
class AppController extends Controller {

var $components = array(‘Session’, ‘Auth’);

function beforeFilter() {

$this->Auth->allow(‘*’);

//Auth Settings
if (!empty($this->params[‘prefix’]) && in_array($this->params[‘prefix’], Configure::read(‘Routing.prefixes’))) {

$this->layout = $this->params[‘prefix’];

//for Administrator
if ($this->params[‘prefix’] == ‘admin’) {
$this->Security->loginOptions = array(‘type’ => ‘basic’, ‘realm’ => ‘Admin Area’);
$this->Security->loginUsers = array(‘admin’ => ‘Basic認証のパスワード’);
$this->Security->requireLogin();
}

//for Member
if ($this->params[‘prefix’] == ‘member’) {
$this->Auth->loginAction = ‘member/users/login’;
$this->Auth->loginRedirect = ‘member/users/index’;
$this->Auth->fields = array(‘username’ => ’email’, ‘password’ => ‘password’);
$this->Auth->autoRedirect = true;
$this->Auth->loginError = "IDかパスワードが正しくありません";
$this->Auth->authError = "Authentication Error";
}
}

}

}
[/php]

このように、AppController内の、beforeFilter内で現在のprefixesの値で分岐させて、Authの設定を切り替えます。上記が一番のポイントで、その他ログインなどは、CookBookに書いてある様にすれば大抵問題なく動きます。

[CakePHP]コントローラー内で一時的に一部validateを無効にする方法

[CakePHP1.2.3]

コントローラ内でvalidationをする際に、全てoffにするのは簡単です。

[php]
$this->Model->save($data, false);
[/php]

と、saveの第二引数にfalseをセットします。

しかし、一部のvalidationのみoffにしたい場合もあるでしょう。そういうときはどうすればいいのでしょうか。
実は、単純に以下のようにするだけなのでした。

[php]
//コントローラ内
unset($this->Account->validate[‘crosslink_url’]);
[/php]

他にも、モデル内でsetValidateなどのメソッドを作って切り替える、などの方法も考えられます。

[CakePHP]paginateではbindModelの第二引数にfalseが必要

[CakePHP1.2.3]

なんか、今開発中なのでしょうがないですが、最近CakePHPのネタばかり書いています。

今回は、コントローラ内でpaginateを呼び出す前にbindModelする際の注意点です。

通常では、paginateはモデル内で定義されたアソシエーションの設定通りにデータを取得します。
しかし、取得前に、bindModelやunbindModelでアソシエーションを一時的に変更することがあると思います。

例えば、Tagのidで絞り込んだArticleの一覧が欲しい場合があります。

そのような時は、以下のようにします。

[php]
//コントローラ内
$this->Article->bindModel(array(‘hasOne’ => array(‘ArticlesTag′)), false);
$this->paginate = array(
‘conditions’ => array(‘ArticlesTag.tag_id’ => $tag_id)
);
$articles = $this->paginate(‘Article’);
[/php]

一番上の、bindModelメソッドの第二引数にfalseを入れるのがミソです。これを入れないと正しく動作してくれません。
この第二引数は、モデルのfindメソッド実行後にモデル内のアソシエーション設定に戻すかどうかのフラグです。
falseを入れると、findメソッドが1回呼ばれた後でもbindした設定が有効になったままになります。

この設定が必要な理由は、pagination呼び出し時に件数を数えるfindと、データを取得するfind、計2回findメソッドが呼ばれるためです。こちらはなかなか気づきにくいところですので、お気をつけ下さい。

[CakePHP]カスタムpaginationを使い分ける方法

[CakePHP1.2.3]

カスタムpaginationはモデル内で、paginateメソッドをオーバーライドすることで、実現できます。

しかしこの方法の欠点としては、このモデルの全てのpaginationでこのカスタム仕様が有効になってしまうことです。例えば、公開ページはカスタム設定を使いたいけれども、管理画面ではカスタム設定を使いたくないという場合はあるかと思います。今回私もそういう使い方をする必要があり、解決方法を考えてみました。

解決方法としては、以下のように、メソッドの第7引数のextra変数を使って切り分けるのが良さそうです。

[php]
//モデル内
function paginate($conditions = null, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null, $extra = array()) {

if (!empty($conditions)) {
$params[‘conditions’] = $conditions;
}
if (!empty($fields)) {
$params[‘fields’] = $fields;
}
if (!empty($order)) {
$params[‘order’] = $order;
}
if (!empty($limit)) {
$params[‘limit’] = $limit;
}
if (!empty($page)) {
$params[‘page’] = $page;
}
if (!empty($recursive)) {
$params[‘recursive’] = $recursive;
}

if (!empty($extra[‘type’]) && $extra[‘type’] == ‘custom’) {
//カスタム設定
return $this->find(‘custom’, $params);
}
else {
//普通のpagination設定
return $this->find(‘all’, $params);
}
}
[/php]

コントローラ側のpaginate設定では、以下の様にします。

[php]
//コントローラー内
$this->paginate = array(
‘conditions’ => array(‘各種条件’),
‘type’ => ‘custom’,
);
[/php]

これで問題なくカスタムpaginationの動作を切り替えることが出来るようになりました。めでたしめでたし。

[CakePHP]関連テーブルをfind(‘list’)する際はrecursive=0にする

[CakePHP1.2.3]

フォームのセレクトボックスを作る際に、コントローラー内でfind(‘list’)で、belongsToの関連データを取得しようとしたら取得できず。調べてみたら、この場合はrecursive=0をセットしないといけないようです。

http://book.cakephp.org/1.3/view/1018/find#find-list-1022

上記リファレンスは1.3ですが、Cakephp1.2でも同様にrecursive=0が必要でした。
地味に気がつかないことがあるのでお気をつけください。 

 

あまり使う場面がないようで、意外とありました。
例えば、Tagで絞り込んだArticleのlistを取得したい際などですね。
そのような場合、以下のようにします。

[php]
$this->Article->bindModel(array(‘hasOne’ => array(‘ArticlesTag’)));

$this->Article->find(‘list’, array(
‘conditions’ => array(‘ArticlesTag.tag_id’ => $tag_id),
‘recursive’ => 0
));
[/php]

開発環境

php5.2
Cakephp1.2.3