#symfony #doctrine
#symfony #доктрина
Вопрос:
У меня есть таблица для запросов пользователей на восстановление паролей. Это его столбцы:
- ID
- idUser
- Дата создания
- Срок действия
- токен
- Истекло
Если пользователь пытается сделать несколько запросов, я хочу найти все строки с его идентификатором, и если они> 1, установите их isExpired = true
равными . При этом я хочу считать действительным только последний запрос.
Как я могу этого добиться?
Вот как я это делаю сейчас, предполагая, что в таблице есть только одна строка с его идентификатором:
if ($request->isMethod('POST')) {
$form->handleRequest($request);
$newPassword = $form->get('password')->getData();
$currentToken = $request->query->get('token');
$em = $this->getDoctrine()->getManager();
$passwRecovery = $em->getRepository('UserBundleEntityPasswordRecovery')->findOneBy(array('token' => $currentToken));
if (empty($passwRecovery)) {
return new Response ("<h3>Access denied!</h3>");
}
else {
if (new DateTime('now') > $passwRecovery->getExpireDate())
{
return new Response ("<h3>Token expired!</h3>");
}
$idUser = $passwRecovery->getIdUser();
$userRecoverPassw = $em->getRepository('UserBundleEntityUser')->findOneBy(array('id' => $idUser));
$userRecoverPassw->setPassword($newPassword);
$em->persist($userRecoverPassw);
$em->flush();
return new Response ("<h3>Password reset ok!</h3>"); }
Учтите, что у меня есть 3 строки с одним и тем же идентификатором пользователя, если я использую:
$passwRecovery = $em->getRepository('UserBundleEntityPasswordRecovery')
->findAll(array('token' => $currentToken));
Я получу 3 результата. Как я могу установить значение isExpired = true
only для первых двух?
Спасибо!
Комментарии:
1. Почему бы просто не устанавливать значение isExpired true каждый раз, когда вы добавляете новую строку восстановления пароля? Также кажется странным, что вы используете один и тот же токен для каждой строки.
2. Я не хочу использовать один и тот же токен более одного раза. Токен уникален и генерируется для каждого отдельного запроса. Я создал столбец IsExpired, чтобы отслеживать все восстановления пароля пользователя, но в то же время я хочу, чтобы действительным был только последний запрос, сделанный пользователем.
3. Если токен уникален, то как findAll в конце вашего вопроса может возвращать более одной записи? И если каждый раз, когда вы добавляете новую запись восстановления, у вас истекает срок действия всех предыдущих записей для этого пользователя, тогда, похоже, ваши требования будут выполнены.
4. Метод findAll() в конце моего вопроса будет искать все одинаковые
idUser
. Это процесс: пользователь получает электронное письмо с прикрепленным токеном. Он нажимает на ссылку, затем программа ищет этот токен в БД, чтобы проверить, действителен ли он. Если токен находится в БД, то программа получит имяidUser
этого пользователя и выполнит поиск других активных запросов. Если есть какие-то запросы, программа их удалит.5. Я добавил решение
Ответ №1:
Это решение, которое в конце сработало для меня, надеюсь, это поможет. Если есть какие-либо лучшие способы сделать то, что я публикую здесь, я открыт для предложений.
public function resetPasswordAction(Request $request) {
$form = $this->createFormBuilder()
->add('password', 'password')
->add('save', 'submit', ['label' => 'Send'])
->getForm();
if ($request->isMethod('POST')) {
$form->handleRequest($request);
$newPassword = $form->get('password')->getData();
$currentToken = $request->query->get('token');
$em = $this->getDoctrine()->getManager();
$passwRecoveryObject = $em->getRepository('UserBundleEntityPasswordRecovery')->findOneBy(array('token' => $currentToken));
if (empty($passwRecoveryObject)) {
return new Response ("Impossible to execute the request!");
}
else {
if (new DateTime('now') > $passwRecoveryObject->getExpireDate())
{
return new Response ("Token expired!");
}
$idUser = $passwRecoveryObject->getIdUser()->getId();
$userRecoverPassw = $em->getRepository('UserBundleEntityPasswordRecovery')->findBy(array('idUser' => $idUser));
$end = end($userRecoverPassw); //$end is the last record of the password_recovery table
$count = count($userRecoverPassw); //count of the rows in password_recovery with the id of the current User
foreach ($userRecoverPassw as $element) { //here i'm setting to 1 the isExpired column for all the rows with the same id, except for the last one
if (--$count <= 0) {
break; }
$element->setIsExpired(1);
$em->persist($element);
$em->flush();
}
$userResetPassw = $em->getRepository('UserBundleEntityUser')->findOneBy(array('id' => $end->getIdUser()->getId())); //User that need to reset the password
if ($end->getIsExpired()==0) {
$userResetPassw->setPassword($newPassword);
$end->setIsExpired(1);
$em->persist($userResetPassw);
$em->flush();
$em->persist($end);
$em->flush();
return new Response ("Password succesfully updated!");
}
else { return new Response ("Expired link!");}
} }
return $this->render('UserBundle:AccountUser:reset_password.html.php', array(
'form' => $form->createView(),));
}