Symfony 4 — хорошая практика удаления собственной учетной записи пользователя при подключении

Я хотел бы, чтобы мои пользователи могли удалять свои собственные учетные записи пользователей. Я сделал SecurityController, где есть мои 3 функции login, logout и deleteUser. Когда я удаляю текущего пользователя в базе данных, появляется эта ошибка:

Вы не можете обновить пользователя из EntityUserProvider, который не содержит идентификатор. Пользовательский объект должен быть сериализован с собственным идентификатором, отображаемым Doctrine.

Когда я удаляю другого пользователя, он работает правильно, потому что он не подключен. Должен ли я сериализовать пользователя и передать его через службу, выйти из системы, а затем удалить его в службе? Или я могу очистить сеанс PHP в контроллере, но я не знаю, как это сделать с помощью symfony4 Я думаю, что это изменилось с версии 4.

<?php

namespace App\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;

use App\Entity\User;
use App\Form\UserType;

class SecurityController extends Controller
{
  /**
   * @Route("/createAdmin", name="create_admin")
   */
    public function createAdminUser(Request $request, UserPasswordEncoderInterface $passwordEncoder)
    {
      $usersRepo = $this->getDoctrine()->getRepository(User::class);
      $uCount = $usersRepo->countAllUsers();

      if ($uCount == 0)
      {
        $user = new User();
        $form = $this->createForm(UserType::class, $user, array(
          'is_fresh_install' => true,
        ));

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            // Encode the password
            $password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
            $user->setPassword($password);

            // save the User
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();

            // Do what you want here before redirecting the user

            return $this->redirectToRoute('login');
        }

        return $this->render('security/register_admin_user.html.twig', array(
          'form' => $form->createView(),
        ));
      } else {
        if ($this->getUser())
        {
          return $this->redirectToRoute('user_account');
        } else {
          return $this->redirectToRoute('login');
        }
      }
    }

    /**
     * @Route("/login", name="login")
     */
    public function login(Request $request, AuthenticationUtils $authUtils)
    {
      $usersRepo = $this->getDoctrine()->getRepository(User::class);
      $uCount = $usersRepo->countAllUsers();

      if ($uCount == 0)
      {
        return $this->redirectToRoute('create_admin');
      } else {
        $error = $authUtils->getLastAuthenticationError();
        $lastUsername = $authUtils->getLastUsername();

        return $this->render('security/login.html.twig', array(
         'last_username' => $lastUsername,
         'error'         => $error,
        ));
      }
    }

    /**
     * @Route("/logout", name="logout")
     */
    public function logout()
    {

    }

    /**
     * @Route("/delete_user/{id}", name="delete_user")
     */
    public function deleteUser($id)
    {
      $em = $this->getDoctrine()->getManager();
      $usrRepo = $em->getRepository(User::class);

      $user = $usrRepo->find($id);
      $em->remove($user);
      $em->flush();

      return $this->redirectToRoute('user_registration');

    }

}

person blakyris    schedule 21.03.2018    source источник
comment
Вы пытались сначала выйти из системы перед удалением учетной записи? Похоже, вы испортили текущий сеанс, если сделали это   -  person Florent Destremau    schedule 21.03.2018
comment
Да, но я должен перенаправить пользователя на страницу входа, поэтому в контроллере я делаю: return $this-›redirectToRoute('logout'); поэтому сеанс пользователя очищается автоматически внутренними функциями symfony. Я ничего не могу сделать после выхода из системы.   -  person blakyris    schedule 21.03.2018
comment
рассмотрите этот ответ, затем stackoverflow.com/a/28828377/2538899   -  person Florent Destremau    schedule 21.03.2018


Ответы (3)


РЕШЕНИЕ:

Вы должны очистить сеанс перед удалением записи пользователя в БД с помощью этого метода:

<?php

use Symfony\Component\HttpFoundation\Session\Session;

// In your deleteUser function...

      $currentUserId = $this->getUser()->getId();
      if ($currentUserId == $id)
      {
        $session = $this->get('session');
        $session = new Session();
        $session->invalidate();
      }

Я не знаю, почему $this->get('session')->invalidate(); не работает напрямую... если кто-то знает :)

person blakyris    schedule 21.03.2018

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

person Martin Fasani    schedule 20.03.2020

Я думаю, вам нужно сериализовать пользователя и передать его через службу. Просто проверьте предыдущие версии, вы обнаружите проблему.

person Amira Bedhiafi    schedule 21.03.2018
comment
Нет, я не знаю, почему мы должны сериализовать его перед удалением. Symfony перезагружает пользователя из БД при каждой перезагрузке страницы. Сессия тоже обновляется. Вот почему мы должны очистить сеанс перед перенаправлением пользователя на другую страницу. - person blakyris; 21.03.2018