Yii2: Логин по email или username?

Как можно реализовать логин по разным полям? Поскольку в форме показывается либо username поле либо email. Мне не хотелось бы так оставлять, валидация происходит нормально, если мыло пустое, то валидирует по имени и на оборот. Сейчас это выглядит вот так.

public function getUser()
    {
        if ($this->_user === false) {
            $this->_user = User::findByUsername($this->username);
                      if ($this->_user === false) {
                                $this->_user = User::findByEmail($this->email);
                       }
        }
        return $this->_user;
    }


В ruls email является safe атрибутом.

Форма во Views
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>

                <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>

                <?= $form->field($model, 'email')->textInput() ?>

                <?= $form->field($model, 'password')->passwordInput() ?>

                <?= $form->field($model, 'rememberMe')->checkbox() ?>

                <div style="color:#999;margin:1em 0">
                     Я забыл пароль <?= Html::a('восстановить', ['password-reset-request']) ?>.
                </div>

                <div class="form-group">
                    <?= Html::submitButton('Вход', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
                </div>

            <?php ActiveForm::end(); ?>


Мне нужно одно общее поле, которое валидировало бы нормально и по мылу и по имени. Возможно поменяю на номера телефонов и будет свой паттерн ввода. Как поступить правильно?
  • Вопрос задан
  • 2994 просмотра
Решения вопроса 1
qonand
@qonand
Software Engineer
Если я правильно понял задачу, и цель стоит в одном поле вводить либо мыло/либо логин/либо телефон, то что мешает сделать так:
1. В модели сделать атрибут, например: $login и его использовать на форме
2. Написать свой валидатор который будет проверять являются ли данные телефон/мылом и т.п.
https://yiiframework.com.ua/ru/doc/guide/2/input-v...
https://yiiframework.com.ua/ru/doc/guide/2/input-v...
3. В методе getUser сделать поиск введенных данных по необходимым полям через OR ?
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
skipOnEmpty подробнее как всегда в доках:
www.yiiframework.com/doc-2.0/yii-validators-valida...
Ответ написан
Комментировать
maxkh
@maxkh
Web developer
Если вы делаете все это в модели - лучшим решением было бы завести отдельную форму, где были бы прописаны rules() для валидации и фильтрации. В этой же форме, можно реализовать вашу логику авторизации.

class Login extends Model
{
    public $identity;
    public $password;

    public function rules()
    {
        return [
            ['identity', 'filter', 'filter' => 'trim'],
            ['identity', 'required'],

            ['password', 'required'],
        ];
    }

    /**
     * @return bool|null|static|User
     */
    public function authenticate()
    {
        if (!$user = User::findIdentityByUsernameOrEmail($this->identity)) {
            $this->addError('identity', Yii::t('app', 'invalid_credentials_on_login'));
            return false;
        }

        if (!$user->validatePassword($this->password)) {
            $this->addError('identity', Yii::t('app', 'invalid_credentials_on_login'));
            return false;
        }

        return $user;
    }
}


/**
     * Finds user by username or email
     *
     * @param string $identity
     * @return static|null
     */
    public static function findIdentityByUsernameOrEmail($identity)
    {
        /**
         * Try to find identity by nickname
         * @var User $user
         */
        if ($user = static::findOne(['username' => $identity, 'status' => self::STATUS_ACTIVE])) {
            return $user;
        }

        /**
         * Try to find identity by email
         * @var LoginAccount $loginAccount
         */
        if ($loginAccount = LoginAccount::findByEmail($identity)) {
            return $loginAccount->getUser()->one();
        }

        return null;
    }


В моем случае авторизация по email или nickname в одном поле, которое имеет общее название identity, а при поиске пользователя я использую 2 модели, так как email в другой таблице.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы