'Symfony\Component\HttpFoundation\File\File' 的序列化是不允许的,Symfony4
Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed, Symfony4
我在 User
class 中添加了头像图片。当我想渲染我的编辑表单时,我得到了这个错误
Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed
我试图根据Symfony Official Documentation在我的User
class中实施\Serializable
来解决问题。但是当我实现它时,它重定向到登录页面并且 Authentication
转向 anon.
并再次登录,它再次重定向到登录页面并保持 anon.
。
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:
<?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
<?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
<?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,
]);
}
}
1. 第一个错误
Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed
- 这是因为
profileAction()
中的这条指令:您将 File
对象分配给头像字段...变得不可序列化。
public function profileAction(Request $request)
{
$user = $this->getUser();
$user->setAvatar(
new File(Constants::UPLOAD_AVATAR.'/'.$user->getAvatar())
);
...
}
您也不能在输入 profileAction()
函数时那样设置头像字段...这会递归更改名称,在名称前添加前缀目录。
2.安全错误,返回登录页面,匿名。身份验证
如果您正确地消除了序列化问题,用户身份验证可以正常进行到身份验证状态...如果您再次遇到登录表单循环匿名问题。状态,您可能必须按照 SF4 中现在的要求实现 EquatableInterface。
希望对您有所帮助。
经过一些调试,我自己找到了解决方案。
问题是,当 User
实体正在实现 UserInterface
时,用户提供者(实际上是 Doctrine,在幕后)试图序列化 User
对象来存储它在会话中,但由于我分配给它的文件 class,它的职业生涯失败了!
为了解决这个问题,首先我尝试从数据库中获取单独的 User
对象,但不幸的是 Doctrine 再次给了我 User
对象的确切引用。(这不是错误。感谢Doctrine. 查询越少越好.
其次,我 clone
在控制器中自己 User
对象,然后将其发送到 UserType
表单,然后一切顺利。
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
class.
的头像字段中将名称文件另存为 string
您的应用程序中可能有一些其他设计,但据我所知,不要将 File
字段直接分配给实施 UserInterface
的 User
实体]!
很好的答案啊,你总结的很完美。
我遇到了同样的问题并找到了解决方法,在刷新 entityManager 后,我只是将用户对象的 imageFile 属性 设置为 null。
它让用户对象更新并在会话中持久化正确的对象,排除文件对象
小心!如果您的表单中有一些错误,symfony 仍会尝试在表单页面呈现时序列化您上传的文件。如果 $form->isValid()
return false,我也必须设置为 null imageFile。
我做过这样的事情:
class User implements UserInterface, Serializable {
// our image
private $profileImage;
/*
Rest of our awesome entity
*/
public function serialize()
{
$this->profileImage = base64_encode($this->profileImage);
}
public function unserialize($serialized)
{
$this->profileImage = base64_decode($this->profileImage);
}
}
而且效果很好。
最近再次活跃于 symfony,通过 symfony 5 工作。
但我所做的是:
- 创建了实现用户界面的用户实体
- 添加了一个实体 Userfile 并在 User 实体中建立了多对一关系
- 使 class 可序列化(这就是窍门)
如果这样做,您可以在通过身份验证时添加 files/photo,并且不会出现该错误
在用户实体中:
/**
* @ORM\OneToMany(targetEntity="UserFile",mappedBy="user", cascade={"remove"})
* @ORM\OrderBy({"created_at" = "DESC"})
*/
protected $userfiles;
用户文件class:
<?php
namespace App\Entity;
use App\Repository\UserFileRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Entity\File as EmbeddedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity(repositoryClass=UserFileRepository::class)
* @Vich\Uploadable
* @ORM\HasLifecycleCallbacks
*/
class UserFile implements \Serializable
{
/**
* Constructor
*/
public function __construct()
{
// voor de VichUploader
$this->image = new EmbeddedFile();
}
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="userfiles")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
* @ORM\OrderBy({"achternaam" = "DESC"})
* @Assert\NotBlank()
*/
protected $user;
/**
* @var string
* @ORM\Column(name="type", type="string", length=20, nullable=true)
*/
protected $type;
//--------------------------------------------------------------------------------
/**
* @ORM\Column(name="created_at", type="datetime", nullable=true)
*
*/
protected $created_at;
/**
* @ORM\Column(name="updated_at", type="datetime", nullable=true)
*
*/
protected $updated_at;
//--------------------------------------------------------------------------------
// de kolommen voor het uploaden van een image via VichUploader
//--------------------------------------------------------------------------------
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* @Vich\UploadableField(mapping="gebruiker_foto",
* fileNameProperty="image.name",
* size="image.size",
* mimeType="image.mimeType",
* originalName="image.originalName",
* dimensions="image.dimensions")
*
* @var File|null
*/
private $imageFile;
/**
* @ORM\Embedded(class="Vich\UploaderBundle\Entity\File")
* @var EmbeddedFile
*/
private $image;
//--------------------------------------------------------------------------------
public function getId(): ?int
{
return $this->id;
}
//--------------------------------------------------------------------------------
public function getUser() : ?User
{
return $this->user;
}
public function setUser(?User $user)
{
$this->user = $user;
return $this;
}
/**
* @return string
*/
public function getType(): ?string
{
return $this->type;
}
/**
* @param string $type
* @return UserFile
*/
public function setType(?string $type): self
{
$this->type = $type;
return $this;
}
//--------------------------------------------------------------------------------
/**
*
*/
public function getCreatedAt()
{
return $this->created_at;
}
/**
*
*/
public function getUpdatedAt()
{
return $this->updated_at;
}
//--------------------------------------------------------------------------------
// callbacks
//--------------------------------------------------------------------------------
/**
* @ORM\PrePersist()
* Hook on pre-persist operations
*/
public function prePersist()
{
$this->created_at = new \DateTime;
$this->updated_at = new \DateTime;
}
/**
* @ORM\PreUpdate()
* Hook on pre-update operations
*/
public function preUpdate()
{
$this->updated_at = new \DateTime;
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function verkleinFoto()
{
if (null === $this->imageFile) {
return;
}
// create smaller image, wel graag vierkante plaatjes!!
$width = 160;
$imagine = new \Imagine\Gd\Imagine();
$image = $imagine->open($this->imageFile);
$size = $image->getSize();
$image->resize($size->widen($width));
$realpath = $this->imageFile->getRealPath();
$image->save($realpath);
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
//$this->file->move($this->getUploadRootDir(), $this->path);
//unset($this->file);
}
//--------------------------------------------------------------------------------
// de setters/getters voor het uploaden van een image via VichUploader
//--------------------------------------------------------------------------------
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* @param File|UploadedFile|null $imageFile
*/
public function setImageFile(?File $imageFile = null): void
{
$this->imageFile = $imageFile;
if (null !== $imageFile) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updated_at = new \DateTimeImmutable();
}
}
public function getImageFile(): ?File
{
return $this->imageFile;
}
public function setImage(EmbeddedFile $image): void
{
$this->image = $image;
}
public function getImage(): ?EmbeddedFile
{
return $this->image;
}
//--------------------------------------------------------------------------------
public function serialize()
{
$this->imageFile = base64_encode($this->imageFile);
}
public function unserialize($serialized)
{
$this->imageFile = base64_decode($this->imageFile);
}
}
这可能对某些人有所帮助,这个问题其实没什么大不了的。只需在实体的 File
字段上添加 @Ignore
注释 - 为我解决了这个问题。
示例:
/**
* @Vich\UploadableField(mapping="users", fileNameProperty="imageName")
* @Ignore()
*/
private ?File $imageFile = null;
我在 User
class 中添加了头像图片。当我想渲染我的编辑表单时,我得到了这个错误
Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed
我试图根据Symfony Official Documentation在我的User
class中实施\Serializable
来解决问题。但是当我实现它时,它重定向到登录页面并且 Authentication
转向 anon.
并再次登录,它再次重定向到登录页面并保持 anon.
。
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:
<?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
<?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
<?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,
]);
}
}
1. 第一个错误
Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed
- 这是因为
profileAction()
中的这条指令:您将File
对象分配给头像字段...变得不可序列化。
public function profileAction(Request $request)
{
$user = $this->getUser();
$user->setAvatar(
new File(Constants::UPLOAD_AVATAR.'/'.$user->getAvatar())
);
...
}
您也不能在输入 profileAction()
函数时那样设置头像字段...这会递归更改名称,在名称前添加前缀目录。
2.安全错误,返回登录页面,匿名。身份验证
如果您正确地消除了序列化问题,用户身份验证可以正常进行到身份验证状态...如果您再次遇到登录表单循环匿名问题。状态,您可能必须按照 SF4 中现在的要求实现 EquatableInterface。
希望对您有所帮助。
经过一些调试,我自己找到了解决方案。
问题是,当 User
实体正在实现 UserInterface
时,用户提供者(实际上是 Doctrine,在幕后)试图序列化 User
对象来存储它在会话中,但由于我分配给它的文件 class,它的职业生涯失败了!
为了解决这个问题,首先我尝试从数据库中获取单独的 User
对象,但不幸的是 Doctrine 再次给了我 User
对象的确切引用。(这不是错误。感谢Doctrine. 查询越少越好.
其次,我 clone
在控制器中自己 User
对象,然后将其发送到 UserType
表单,然后一切顺利。
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
class.
string
您的应用程序中可能有一些其他设计,但据我所知,不要将 File
字段直接分配给实施 UserInterface
的 User
实体]!
很好的答案啊,你总结的很完美。
我遇到了同样的问题并找到了解决方法,在刷新 entityManager 后,我只是将用户对象的 imageFile 属性 设置为 null。
它让用户对象更新并在会话中持久化正确的对象,排除文件对象
小心!如果您的表单中有一些错误,symfony 仍会尝试在表单页面呈现时序列化您上传的文件。如果 $form->isValid()
return false,我也必须设置为 null imageFile。
我做过这样的事情:
class User implements UserInterface, Serializable {
// our image
private $profileImage;
/*
Rest of our awesome entity
*/
public function serialize()
{
$this->profileImage = base64_encode($this->profileImage);
}
public function unserialize($serialized)
{
$this->profileImage = base64_decode($this->profileImage);
}
}
而且效果很好。
最近再次活跃于 symfony,通过 symfony 5 工作。
但我所做的是:
- 创建了实现用户界面的用户实体
- 添加了一个实体 Userfile 并在 User 实体中建立了多对一关系
- 使 class 可序列化(这就是窍门)
如果这样做,您可以在通过身份验证时添加 files/photo,并且不会出现该错误
在用户实体中:
/**
* @ORM\OneToMany(targetEntity="UserFile",mappedBy="user", cascade={"remove"})
* @ORM\OrderBy({"created_at" = "DESC"})
*/
protected $userfiles;
用户文件class:
<?php
namespace App\Entity;
use App\Repository\UserFileRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Entity\File as EmbeddedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity(repositoryClass=UserFileRepository::class)
* @Vich\Uploadable
* @ORM\HasLifecycleCallbacks
*/
class UserFile implements \Serializable
{
/**
* Constructor
*/
public function __construct()
{
// voor de VichUploader
$this->image = new EmbeddedFile();
}
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="userfiles")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
* @ORM\OrderBy({"achternaam" = "DESC"})
* @Assert\NotBlank()
*/
protected $user;
/**
* @var string
* @ORM\Column(name="type", type="string", length=20, nullable=true)
*/
protected $type;
//--------------------------------------------------------------------------------
/**
* @ORM\Column(name="created_at", type="datetime", nullable=true)
*
*/
protected $created_at;
/**
* @ORM\Column(name="updated_at", type="datetime", nullable=true)
*
*/
protected $updated_at;
//--------------------------------------------------------------------------------
// de kolommen voor het uploaden van een image via VichUploader
//--------------------------------------------------------------------------------
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* @Vich\UploadableField(mapping="gebruiker_foto",
* fileNameProperty="image.name",
* size="image.size",
* mimeType="image.mimeType",
* originalName="image.originalName",
* dimensions="image.dimensions")
*
* @var File|null
*/
private $imageFile;
/**
* @ORM\Embedded(class="Vich\UploaderBundle\Entity\File")
* @var EmbeddedFile
*/
private $image;
//--------------------------------------------------------------------------------
public function getId(): ?int
{
return $this->id;
}
//--------------------------------------------------------------------------------
public function getUser() : ?User
{
return $this->user;
}
public function setUser(?User $user)
{
$this->user = $user;
return $this;
}
/**
* @return string
*/
public function getType(): ?string
{
return $this->type;
}
/**
* @param string $type
* @return UserFile
*/
public function setType(?string $type): self
{
$this->type = $type;
return $this;
}
//--------------------------------------------------------------------------------
/**
*
*/
public function getCreatedAt()
{
return $this->created_at;
}
/**
*
*/
public function getUpdatedAt()
{
return $this->updated_at;
}
//--------------------------------------------------------------------------------
// callbacks
//--------------------------------------------------------------------------------
/**
* @ORM\PrePersist()
* Hook on pre-persist operations
*/
public function prePersist()
{
$this->created_at = new \DateTime;
$this->updated_at = new \DateTime;
}
/**
* @ORM\PreUpdate()
* Hook on pre-update operations
*/
public function preUpdate()
{
$this->updated_at = new \DateTime;
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function verkleinFoto()
{
if (null === $this->imageFile) {
return;
}
// create smaller image, wel graag vierkante plaatjes!!
$width = 160;
$imagine = new \Imagine\Gd\Imagine();
$image = $imagine->open($this->imageFile);
$size = $image->getSize();
$image->resize($size->widen($width));
$realpath = $this->imageFile->getRealPath();
$image->save($realpath);
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
//$this->file->move($this->getUploadRootDir(), $this->path);
//unset($this->file);
}
//--------------------------------------------------------------------------------
// de setters/getters voor het uploaden van een image via VichUploader
//--------------------------------------------------------------------------------
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* @param File|UploadedFile|null $imageFile
*/
public function setImageFile(?File $imageFile = null): void
{
$this->imageFile = $imageFile;
if (null !== $imageFile) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updated_at = new \DateTimeImmutable();
}
}
public function getImageFile(): ?File
{
return $this->imageFile;
}
public function setImage(EmbeddedFile $image): void
{
$this->image = $image;
}
public function getImage(): ?EmbeddedFile
{
return $this->image;
}
//--------------------------------------------------------------------------------
public function serialize()
{
$this->imageFile = base64_encode($this->imageFile);
}
public function unserialize($serialized)
{
$this->imageFile = base64_decode($this->imageFile);
}
}
这可能对某些人有所帮助,这个问题其实没什么大不了的。只需在实体的 File
字段上添加 @Ignore
注释 - 为我解决了这个问题。
示例:
/**
* @Vich\UploadableField(mapping="users", fileNameProperty="imageName")
* @Ignore()
*/
private ?File $imageFile = null;