Для восстановления пароля в 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 в форме, отправляется письмо с ссылкой для сброса пароля. Пользователь может перейти по этой ссылке и ввести новый пароль. После успешного сброса пароля пользователь будет автоматически аутентифицирован и перенаправлен на главную страницу.