不允许对"Symfony \ Component \ HttpFoundation \ File \ File"进行序列化,Symfony4 [英] Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed, Symfony4

查看:411
本文介绍了不允许对"Symfony \ Component \ HttpFoundation \ File \ File"进行序列化,Symfony4的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将头像图像添加到我的User类中.当我要呈现编辑表单时,出现此错误

I've added an avatar image to my User class. When I wanted to render my edit form, I got this error

不允许对"Symfony \ Component \ HttpFoundation \ File \ File"进行序列化

Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed

我试图根据User类中实现\Serializable来解决问题> Symfony官方文档.但是当我实现它时,它重定向到登录页面,而Authentication变为anon.,然后再次登录,它又重定向到登录页面并保持anon..

I tried to solve the problem by implementing \Serializable in my User class according to Symfony Official Documentation. But when I implemented that,It redirected to login page and the Authentication turned to anon. and by logging in again, it redirected to login page again and stay anon. too.

我应该提到我已经设置了一些授权.如果您是匿名",它将把您重定向到登录页面.并希望访问一些受保护的路由.

I should mention that I have set some Authorizations. It will redirect you to the log in page if you are "anon." and want to access some protected routes.

这是我的UserEntity,User.php:

Here is my UserEntity, User.php:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;


/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\Table(name="user")
 * @UniqueEntity(fields={"username"}, message="This username has been taken!")
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", unique=true,length=191)
     * @Assert\NotBlank()
     * @Assert\Length(min="5", minMessage="Username most contain at least 5 characters!")
     */
    private $username;

    /**
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="string")
     */
    private $displayName;

    /**
     * @ORM\Column(type="boolean")
     */
    private $showAdminBar;

    /**
     * @ORM\OneToMany(targetEntity="Post", mappedBy="owner")
     */
    private $posts;

    /**
     * @ORM\Column(type="string")
     */
    private $avatar;

    /**
     * @Assert\NotBlank(groups={"Registration"})
     * @Assert\Length(min="6", minMessage="Password most contain at least 6 characters!")
     */
    private $plainPassword;

    public function getUsername()
    {
        return $this->username;
    }

    public function getRoles()
    {
        return ['ROLE_ADMIN'];
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getSalt()
    {
    }

    public function eraseCredentials()
    {
        $this->plainPassword = null;
    }

    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->displayName,
            $this->avatar,
            // see section on salt below
            // $this->salt,
        ));
    }

    /**
     * @param mixed $username
     */
    public function setUsername($username)
    {
        $this->username = $username;
    }

    /**
     * @param mixed $password
     */
    public function setPassword($password)
    {
        $this->password = $password;
    }

    /**
     * @return mixed
     */
    public function getPlainPassword()
    {
        return $this->plainPassword;
    }

    /**
     * @param mixed $plainPassword
     */
    public function setPlainPassword($plainPassword)
    {
        $this->plainPassword = $plainPassword;
        //To make sure that Doctrine see the entity as "dirty"
        $this->password = null;
    }

    /**
     * @return mixed
     */
    public function getDisplayName()
    {
        return $this->displayName;
    }

    /**
     * @param mixed $displayName
     */
    public function setDisplayName($displayName)
    {
        $this->displayName = $displayName;
    }

    /**
     * @return mixed
     */
    public function getShowAdminBar()
    {
        return $this->showAdminBar;
    }

    /**
     * @param mixed $showAdminBar
     */
    public function setShowAdminBar($showAdminBar)
    {
        $this->showAdminBar = $showAdminBar;
    }

    /**
     * @return mixed
     */
    public function getPosts()
    {
        return $this->posts;
    }

    /**
     * @param mixed $posts
     */
    public function setPosts($posts)
    {
        $this->posts = $posts;
    }

    /**
     * @return mixed
     */
    public function getAvatar()
    {
        return $this->avatar;
    }

    /**
     * @param mixed $avatar
     */
    public function setAvatar($avatar)
    {
        $this->avatar = $avatar;
    }

    /**
     * @param mixed $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }
}

这是我的UserController.php

Here is my UserController.php

<?php

namespace App\Controller\Admin;

use App\Constants;
use App\Entity\User;
use App\Form\UserType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;


/**
 * @Route("/admin/user")
 * @Security("is_granted('ROLE_ADMIN')")
 */
class UserController extends Controller
{
    /**
     * @Route("/profile", name="admin_user_profile")
     */
    public function profileAction(Request $request)
    {
        $user = $this->getUser();

        $user->setAvatar(
            new File(Constants::UPLOAD_AVATAR.'/'.$user->getAvatar())
        );


        $form = $this->createForm(UserType::class, $user);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $user = $form->getData();


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

            $this->addFlash('success', 'Your Info Has Been Updated!');

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


        return $this->render('admin/user/profile.html.twig', [
            'user' => $user,
            'form' => $form->createView()
        ]);
    }

    /**
     * @Route("/list", name="admin_user_list")
     */
    public function listAction(Request $request)
    {
        $em = $this->getDoctrine()->getManager();
        $users = $em->getRepository(User::class)
            ->findAll();

        return $this->renderView('admin/user/list.html,twig',[
            'users' => $users
        ]);
    }
}

这是我的UserForm UserType.php

Here is my UserForm, UserType.php

<?php

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('displayName')
            ->add('plainPassword', RepeatedType::class, [
                'type' => PasswordType::class
            ])
            ->add('avatar',FileType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}

推荐答案

经过一些调试,我自己找到了解决方案.

After some debugging I found the solution myself.

问题是,当User实体正在实现UserInterface时,用户提供者(实际上是幕后的主义)试图对User对象进行序列化以将其存储在会话中,但是由于文件的原因我把它分配到这堂课上,它失败了!

The problem is, when User Entity was implementing the UserInterface, the user provider(actually the Doctrine, behind the scene) tried to Serializing the User object to store it in the session but because of the file that I assigned it to this class, it fails it's career!

为解决该问题,首先我尝试从数据库中获取单独的User对象,但不幸的是,Doctrine再次为我提供了User对象的确切引用.(那不是错误.感谢Doctrine.它太聪明了,以至于尽可能少地查询).

To solve the problem, first I tried to fetch separate User object from database but unfortunately Doctrine gave me the exact reference of the User object again.(That's not a bug. Thanks to Doctrine. It's too smart to query as less as possible).

第二,我先在控制器中clone clone对象,然后将其发送到UserType表单,然后一切顺利.

Second, I clone the User object myself in the controller before sending it to the UserType form, and then everything went well.

但这不是最佳实践,因为您可能还有其他一些选择 注册,配置文件更新或您遇到的其他情况下的问题 可能具有User类.

But that is not the best practice because you may have some other problems with registration, profile update or other scenarios that you may have with User class.

在我的应用程序中,我添加了另一个名为Media的实体,它与文件系统一起存储文件,每个实体(如User)都需要某种媒体(就像此处的用户头像),与之的关系为ManyToOne这个实体.在这种情况下,您只需在User类的头像字段中将名称文件另存为string.

In my application, I added another entity called Media and it stores the files with the file system and each entity like User which need some media (Like user avatar here), just have a ManyToOne relationship with this entity. In this case you can just save the name file as string in avatar field in User class.

您的应用程序中可能还有其他设计,但据我所知,请勿将File字段直接分配给实现UserInterfaceUser实体!

You may have some other designs in your application but as I experienced, Do not assign a File field directly to the User entity which is implementing UserInterface!

这篇关于不允许对"Symfony \ Component \ HttpFoundation \ File \ File"进行序列化,Symfony4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆