CakePHPでユーザーIDかメールアドレスどちらでもログインできるようにする方法

認証時に、ユーザIDとパスワードなどの組み合わせだけではなく、
メールアドレスとパスワード等、複数のカラムどれでもログインできるようにする方法。

サンプル

Authコンポーネントをそのまま使用。
一方の組み合わせで認証に失敗したら、もう一度、別カラムを参照してログインを試みる。
ビューのinputタグのnameには一組目のカラム名をセットしておく。

<?php
class UsersController extends AppController {
    var $components = array('Auth');

    function beforeFilter() {
        parent::beforeFilter();

    // 一組目の参照カラム設定
        $this->Auth->fields = array(
            'username' => 'username1',
            'password' => 'password',
        );
        $this->Auth->autoRedirect = false; // 自動でリダイレクトしない

        $model = $this->Auth->userModel;
        if ($this->params['action'] === 'login' && isset($this->data[$model][$this->Auth->fields['password']])) {
            // 一度認証を行うとpasswordフィールドにNULLが設定されてしまうので退避させる
      // Configureではなく、コントローラのプロパティなどに保存してもいい
            $password = $this->Auth->password($this->data[$model][$this->Auth->fields['password']]);
            Configure::write($model . '.password', $password);
        }
    }

    function login() {
        if (!empty($this->data) {
            if ($this->Auth->user()) {
                // 一組目の認証に成功した場合はリダイレクト
                $this->redirect($this->Auth->redirect()); 
            } else {
                // 失敗した場合
                $field = 'username2';
                $data  = $this->data;
                $model = $this->Auth->userModel;

                // データを再セット
                $data[$model][$this->Auth->fields['password']] = Configure::read($model . '.password');
                $data[$model][$field] = $data[$model][$this->Auth->fields['username']];
              // 別カラムを参照するように変更
          $this->Auth->fields['username'] = $field;

                // もう一度ログインを試みる
                if ($this->Auth->login($data)) {
                    // sessionのメッセージを削除
                    $this->Session->del('Message.auth');
                    $this->redirect($this->Auth->redirect()); 
                }
            }
        }
    }
}

※8/4 一部修正


SQLが複数呼ばれることになるので、可能ならば下記ページで紹介されてるやり方のほうがいいかも。

http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=1128&forum=8&post_id=2297