Компонент CakePHP Auth с использованием 2 таблиц

CakePHP версия 1.2.5

Я бы хотел, чтобы у одного пользователя было несколько адресов электронной почты.

Я бы хотел, чтобы у одного пользователя был один пароль.

Я хотел бы, чтобы пользователи входили в систему, используя любой из своих нескольких адресов электронной почты и один пароль.

Я создал таблицу пользователей с идентификатором и паролем.

Я создал таблицу user_email_addresses с полем id, полем user_id и полем email_address.

Вопрос:

Как я могу изменить компонент auth минимально, чтобы искать "имя пользователя» в этом случае, "адрес электронной почты", в таблице user_email_addresses и "пароль" в таблице пользователей?

Похоже, что изменение метода identifier в компоненте auth может сделать это. Но я думаю, что изменение компонента auth напрямую - плохая идея - есть идеи, как расширить и все же возможно изменить метод идентификации?http://cakebaker.42dh.com/2009/09/08/extending-cakephps-core-components/ или, возможно, назначить другой объект аутентификации?

Стартовая строка 774:

    function identify($user = null, $conditions = null) {
    if ($conditions === false) {
        $conditions = null;
    } elseif (is_array($conditions)) {
        $conditions = array_merge((array)$this->userScope, $conditions);
    } else {
        $conditions = $this->userScope;
    }
    if (empty($user)) {
        $user = $this->user();
        if (empty($user)) {
            return null;
        }
    } elseif (is_object($user) && is_a($user, 'Model')) {
        if (!$user->exists()) {
            return null;
        }
        $user = $user->read();
        $user = $user[$this->userModel];
    } elseif (is_array($user) && isset($user[$this->userModel])) {
        $user = $user[$this->userModel];
    }

    if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$this->userModel . '.' . $this->fields['username']]))) {

        if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']])  && !empty($user[$this->fields['password']])) {
            if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
                return false;
            }
            $find = array(
                $this->userModel.'.'.$this->fields['username'] => $user[$this->fields['username']],
                $this->userModel.'.'.$this->fields['password'] => $user[$this->fields['password']]
            );
        } elseif (isset($user[$this->userModel . '.' . $this->fields['username']]) && !empty($user[$this->userModel . '.' . $this->fields['username']])) {
            if (trim($user[$this->userModel . '.' . $this->fields['username']]) == '=' || trim($user[$this->userModel . '.' . $this->fields['password']]) == '=') {
                return false;
            }
            $find = array(
                $this->userModel.'.'.$this->fields['username'] => $user[$this->userModel . '.' . $this->fields['username']],
                $this->userModel.'.'.$this->fields['password'] => $user[$this->userModel . '.' . $this->fields['password']]
            );
        } else {
            return false;
        }
        $model =& $this->getModel();
        $data = $model->find(array_merge($find, $conditions), null, null, 0);
        if (empty($data) || empty($data[$this->userModel])) {
            return null;
        }
    } elseif (!empty($user) && is_string($user)) {
        $model =& $this->getModel();
        $data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));

        if (empty($data) || empty($data[$this->userModel])) {
            return null;
        }
    }

    if (!empty($data)) {
        if (!empty($data[$this->userModel][$this->fields['password']])) {
            unset($data[$this->userModel][$this->fields['password']]);
        }
        return $data[$this->userModel];
    }
    return null;
}

Ответы на вопрос(1)

Решение Вопроса

AuthComponent::identify() принимает два параметра,$user а также$conditions

        $conditions = null;
} elseif (is_array($conditions)) {
        $conditions = array_merge((array)$this->userScope, $conditions);
} else {
        $conditions = $this->userScope;
}

Глядя на приведенный фрагмент, если вы передаетеfalse как$conditionsметод будет выполняться без модельных условий.

Кроме того, глядя на остальную часть кода, если вы передаете$user значение типаstringэто победиловыполнить большую часть кода, связанного с пользователем, пока он не попадет сюда:

} elseif (!empty($user) && is_string($user)) {
        $model =& $this->getModel();
        $data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));

        if (empty($data) || empty($data[$this->userModel])) {
                return null;
        }
}

Вот оно работаетModel::escapeField(), без параметров, который возвращает экранированную версиюUser.id (по умолчанию) и сопоставляет это поле со строкой, которая была передана. Затем оно объединяется с$conditions массив и выполняет.Model::find()

Можно с уверенностью сказать, что если строка является пользователемID и нет никаких условий, он будет каждый раз находить человека с этим ID.

Таким образом, вы должны иметь возможность расширять AuthComponent, чтобы делать то, что вы хотите, так:

// app/controllers/components/app_auth.php
<!--?php
App::import('Component', 'Auth');
class AppAuthComponent extends AuthComponent {
/**
 * Custom user identification
 */
    function identify($user=null, $conditions=null) {
        // get the model AuthComponent is configured to use
        $model =& $this--->getModel(); // default is User
        // do a query that will find a User record when given successful login data
        $user = $model->find('first', array('conditions' => array(
            'EmailAddress.' . $this->fields['username'] => $user[$this->userModel][$this->fields['username']],
            'User.' . $this->fields['password'] => $user[$this->userModel][$this->fields['password']],
        ));
        // return null if user invalid
        if (!$user) {
            return null; // this is what AuthComponent::identify would return on failure
        }
        // call original AuthComponent::identify with string for $user and false for $conditions
        return parent::identify($user[$this->userModel][$model->primaryKey], false);
    }
}
?>

Вам придется заменить все ссылки на Auth на AppAuth в вашем приложении, если вы не будете следовать этомуудобный совет (подход в комментариях хорош).

 BWelfel13 нояб. 2009 г., 01:51
Спасибо, deizel - именно то, что я искал!

Ваш ответ на вопрос