Как восстановить пароль в yii2?

Для восстановления пароля в Yii2 вам следует выполнить следующие шаги:

1. Создайте экшен "passwordResetRequest" в контроллере, который будет отображать форму для ввода email, с помощью которого пользователь запросит восстановление пароля. В этом экшене вы можете использовать модель User, чтобы проверить наличие пользователя с введенным email.

public function actionPasswordResetRequest()
{
    $model = new PasswordResetRequestForm();

    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
        if ($model->sendEmail()) { // Отправка письма для восстановления пароля
            Yii::$app->session->setFlash('success', 'На вашу почту отправлено письмо с инструкцией по восстановлению пароля.');
            return $this->goHome();
        } else {
            Yii::$app->session->setFlash('error', 'Не удалось отправить письмо на вашу почту. Пожалуйста, свяжитесь с администратором.');
        }
    }

    return $this->render('passwordResetRequest', [
        'model' => $model,
    ]);
}

2. Создайте новую форму "passwordResetRequest.php" с полем для ввода email и кнопкой отправки формы:

<?php

use yiihelpersHtml;
use yiibootstrapActiveForm;

/* @var $this yiiwebView */
/* @var $model appmodelsPasswordResetRequestForm */

$this->title = 'Восстановление пароля';
$this->params['breadcrumbs'][] = $this->title;
?>

<h1><?= Html::encode($this->title) ?></h1>

<p>Введите свой адрес электронной почты. На него будет отправлено письмо с инструкцией по восстановлению пароля.</p>

<?php $form = ActiveForm::begin(['id' => 'password-reset-request-form']) ?>

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

<div class="form-group">
    <?= Html::submitButton('Отправить', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end() ?>

3. Создайте экшен "resetPassword" в контроллере, который будет проверять отправленный пользователю токен и отображать форму для ввода нового пароля:

public function actionResetPassword($token)
{
    try {
        $model = new ResetPasswordForm($token);
    } catch (InvalidArgumentException $e) {
        throw new BadRequestHttpException($e->getMessage());
    }

    if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
        Yii::$app->session->setFlash('success', 'Ваш пароль был успешно изменен.');
        return $this->goHome();
    }

    return $this->render('resetPassword', [
        'model' => $model,
    ]);
}

4. Создайте форму "resetPassword.php" с полями для ввода нового пароля и подтверждения:

<?php

use yiihelpersHtml;
use yiibootstrapActiveForm;

/* @var $this yiiwebView */
/* @var $model appmodelsResetPasswordForm */

$this->title = 'Сброс пароля';
$this->params['breadcrumbs'][] = $this->title;
?>

<h1><?= Html::encode($this->title) ?></h1>

<p>Пожалуйста, введите ваш новый пароль:</p>

<?php $form = ActiveForm::begin(['id' => 'reset-password-form']) ?>

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

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

<div class="form-group">
    <?= Html::submitButton('Сохранить', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end() ?>

5. Вам понадобится модель для восстановления пароля "PasswordResetRequestForm" и модель для сброса пароля "ResetPasswordForm". Обе модели должны реализовывать трейт "UserTrait".

Модель "PasswordResetRequestForm" будет проверять, существует ли пользователь с введенным email, и отправлять письмо с токеном для сброса пароля:

class PasswordResetRequestForm extends Model
{
    public $email;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['email'], 'required'],
            [['email'], 'email'],
            [['email'], 'exist',
              'targetClass' => 'appmodelsUser',
              'filter' => ['status' => User::STATUS_ACTIVE],
              'message' => 'Нет пользователя с таким email.'
            ],
        ];
    }

    /**
     * Отправляет письмо для восстановления пароля.
     * @return bool
     */
    public function sendEmail()
    {
        $user = User::findOne([
            'status' => User::STATUS_ACTIVE,
            'email' => $this->email,
        ]);

        if ($user) {
            $user->generatePasswordResetToken();
            if ($user->save()) {
                return Yii::$app
                    ->mailer
                    ->compose(
                        ['html' => 'passwordResetToken-html'],
                        ['user' => $user]
                    )
                    ->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot'])
                    ->setTo($this->email)
                    ->setSubject('Восстановление пароля для ' . Yii::$app->name)
                    ->send();
            }
        }

        return false;
    }
}

Модель "ResetPasswordForm" будет проверять, правильность токена и паролей, и обновлять пароль пользователя:

class ResetPasswordForm extends Model
{
    public $password;
    public $password_repeat;

    /**
     * @var appmodelsUser|null
     */
    private $_user;

    /**
     * Создает модель с переданным токеном.
     * @param string $token
     * @param array $config
     * @throws InvalidArgumentException
     */
    public function __construct($token, $config = [])
    {
        if (empty($token) || !is_string($token)) {
            throw new InvalidArgumentException('Необходим токен для сброса пароля.');
        }
        $this->_user = User::findByPasswordResetToken($token);
        if (!$this->_user) {
            throw new InvalidArgumentException('Неправильный токен для сброса пароля.');
        }
        parent::__construct($config);
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['password', 'password_repeat'], 'required'],
            [['password', 'password_repeat'], 'string', 'min' => 6],
            ['password_repeat', 'compare', 'compareAttribute' => 'password'],
        ];
    }

    /**
     * Сбрасывает пароль пользователя.
     * @return bool
     */
    public function resetPassword()
    {
        $user = $this->_user;
        $user->setPassword($this->password);
        $user->removePasswordResetToken();

        return $user->save(false);
    }
}

6. Настройте SMTP для отправки писем в файле конфигурации Yii2 (обычно "config/web.php"):

'components' => [
    'mailer' => [
        'class' => 'yiiswiftmailerMailer',
        'useFileTransport' => false,
        'transport' => [
            'class' => 'Swift_SmtpTransport',
            'host' => 'smtp.example.com',
            'username' => '[email protected]',
            'password' => 'your_email_password',
            'port' => '587',
            'encryption' => 'tls',
        ],
    ],
],

7. Создайте шаблон письма для восстановления пароля в папке "mail" (например, "views/mail/passwordResetToken-html.php"):

<p>Здравствуйте <?= Html::encode($user->username) ?>,</p>

<p>Перейдите по ссылке ниже, чтобы восстановить свой пароль:</p>

<?= Html::a('Восстановить пароль', Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token])) ?>

Теперь, когда пользователь вводит email в форме, отправляется письмо с ссылкой для сброса пароля. Пользователь может перейти по этой ссылке и ввести новый пароль. После успешного сброса пароля пользователь будет автоматически аутентифицирован и перенаправлен на главную страницу.