doujing6053 2018-11-03 11:55
浏览 44
已采纳

Symfony 4 Validator - 如果无效则自动注销

I wanted to validate my User Object ($user) with the Symfony Validator and return a JsonResponse ($response) if the form input data is valid / is not valid. But I have the issue that I get logged out automatically when the data could not be validated. I have to login again and this is not the behaviour I expect when some data ist not valid. I found a workaround (see comments below) but this is not very satisfying :/

Here is the method of my Controller:

 /**
 * Update user profile data
 *
 * @Route("/api/users/updateprofile")
 * @Security("is_granted('USERS_LIST')")
 */

public function apiProfileUpdate(ValidatorInterface $validator, FlashMessageBuilder $flashMessageBuilder)
{
    $request = Request::createFromGlobals();
    // Prepare Response
    $response = new JsonResponse();
    $response->setData([]);
    /** @var User $user */
    $user = $this->getUser();
    $oldName = $user->getName();
    $oldEmail = $user->getEmail();

    $user->setName($request->request->get('name'));
    $user->setEmail($request->request->get('email'));

    $errors = $validator->validate($user);
    if (count($errors) > 0) { // if this -> auto logout
        $user->setName($oldName); // if I set the both attributes back to the old value
        $user->setEmail($oldEmail); // then I don't get logged out automatically but this is just a workaround and not satisfying
        $entityManager = $this->getDoctrine()->getManager(); // forgot to remove this
        $entityManager->persist($user); // and this line, this is actually deleted in the real code

        foreach ($errors as $error) {
            $errorMessage = $error->getMessage();
            $errorField = $error->getPropertyPath();
            $flashMessageBuilder->addErrorMessage($errorMessage, $errorField);
        };

        return $response;
    }

    $entityManager = $this->getDoctrine()->getManager();
    $entityManager->persist($user);
    $entityManager->flush();

    $flashMessageBuilder->addSuccessMessage("Success!");
    return $response;
}

Sorry for my bad english and thank you in advance!

  • 写回答

1条回答 默认 最新

  • doudou1897 2018-11-03 12:54
    关注

    You are persisting the User Object even if there are errors in validation, which can cause the problem with the logout.

    Try to update ONLY in case there is no validation error:

    public function apiProfileUpdate(ValidatorInterface $validator, FlashMessageBuilder $flashMessageBuilder)
    {
        $request = Request::createFromGlobals();
    
        // Prepare Response
        $response = new JsonResponse();
        $response->setData([]);
    
        /** @var User $user */
        $user = $this->getUser();
    
        $user->setName($request->request->get('name'));
        $user->setEmail($request->request->get('email'));
    
        $errors = $validator->validate($user);
        if (count($errors) == 0) {
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($user);
            $entityManager->flush();
    
            $flashMessageBuilder->addSuccessMessage("Success!");
            return $response;
        }
    
        foreach ($errors as $error) {
            $errorMessage = $error->getMessage();
            $errorField = $error->getPropertyPath();
            $flashMessageBuilder->addErrorMessage($errorMessage, $errorField);
        };
    
        return $response;
    }
    

    But I think you should not mix API calls and the classical form approach utilizing FlashMessages, instead return a proper JSON result.

    So consider to change the code accordingly:

    public function apiProfileUpdate(ValidatorInterface $validator, FlashMessageBuilder $flashMessageBuilder)
    {
        $request = Request::createFromGlobals();
    
        /** @var User $user */
        $user = $this->getUser();
    
        $user->setName($request->request->get('name'));
        $user->setEmail($request->request->get('email'));
    
        $errors = $validator->validate($user);
        if (count($errors) == 0) {
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($user);
            $entityManager->flush();
    
            return new JsonResponse(['success' => true]);
        }
    
        $data = [];
        foreach ($errors as $error) {
            $data[$error->getPropertyPath()] = $error->getMessage();
        };
    
        return new JsonResponse(['success' => false, 'errors' => $data], 400);
    }
    

    Now your calling code can handle a 200 result (success) and the error case with status code 400 and display the error messages for all failed fields from the errors part in the result body.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#.net#的问题:End Function
  • ¥50 用AT89C52单片机设计一个温度测量与控制电路
  • ¥15 无法import pycausal
  • ¥15 VS2022创建MVC framework提示:预安装的程序包具有对缺少的注册表值的引用
  • ¥15 weditor无法连接模拟器Local server not started, start with?
  • ¥20 6-3 String类定义
  • ¥15 嵌入式--定时器使用
  • ¥20 51单片机学习中的问题
  • ¥30 Windows Server 2016利用兩張網卡處理兩個不同網絡
  • ¥15 Python中knn问题