我的主页横幅上有四张图片,我希望能够使用Symfony表单立即更新它们。
我完全按照Vich上传器文档(更新的At-Entity 和所有内容)中所述设置图片实体
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Image
*
* @ORM\Table(name="app_image")
* @ORM\Entity
* @Vich\Uploadable
*/
class Image {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @Vich\UploadableField(mapping="dashboard", fileNameProperty="imageName", size="imageSize")
*
* @var File
*/
private $imageFile;
/**
* @ORM\Column(type="integer")
*
* @var integer
*/
private $imageSize;
/**
* @var string
* @ORM\Column(type="string", nullable=false)
*/
private $imageName;
/**
* @ORM\Column(type="datetime")
*
* @var \DateTime
*/
private $updatedAt;
/**
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImageFile(?File $image = null): void
{
$this->imageFile = $image;
if (null !== $image) {
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getImageFile(): ?File
{
return $this->imageFile;
}
public function setImageName(?string $imageName): void
{
$this->imageName = $imageName;
}
public function getImageName(): ?string
{
return $this->imageName;
}
public function setImageSize(?int $imageSize): void
{
$this->imageSize = $imageSize;
}
public function getImageSize(): ?int
{
return $this->imageSize;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set updatedAt
*
* @param \DateTime $updatedAt
*
* @return Image
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* @return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
}
由于四个图像已经存在,我只添加了一个动作来将图像更新到我的控制器
/**
* @Route("/uploadImage/{id}", name="appBundle_upload_image", requirements={"id" = "\d+"})
* @Security("is_granted('ROLE_ATTACHEMENT_ADMIN')")
*/
public function uploadAction(Request $request, $id){
$repository = $this->getDoctrine()->getRepository('AppBundle:Image');
$em = $this->getDoctrine ()->getManager ();
$image = $repository->findOneById($id);
$form = $this->createForm(UploadImageType::class, $image);
$form->handleRequest($request);
if ($form->isValid() ) {
$em->flush();
return $this->redirectToRoute('index');
}
return $this->render('AppBundle:Image:upload.html.twig', array(
'form' => $form->createView(),
'image' => $image,
));
}
我的数据库表中已经有了一些图片,所以我可以访问我的控制器动作的路径,渲染的表单只包含这个:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('imageFile', VichImageType::class, [
'required' => false,
'allow_delete' => false,
'download_label' => '...',
'download_uri' => true,
'image_uri' => true,
]);
}
正如您所看到的,我从基本文档中做了很多改变。 无论如何,当用例如去那条路线时ID 7 ,图片7显示在 download_uri 下,当转储imageName或UpdatedAt时,它与我的数据库表中显示的数据相同。但是当我尝试上传一张应该替换旧图片的新图片时,我收到错误说
实体AppBundle \ Entity \ Image @ 0000000075aa1d6c00000000789d890b未受管理。如果实体从数据库中获取或通过EntityManager#persist
注册为new,则对其进行管理
或者有时候它会像奇迹一样经历我的重定向,但我的数据库表中没有任何改变,所以旧图片没有被替换或任何东西。
我经常搜索很多 Entity not managed 错误的解决方案,或者因为没有更改属性而没有更新。但他们都没有解决我的问题。
您是否在我的代码中看到可能导致问题的任何内容?
更新
我将@nifr的setImageFile方法添加到我的Image Entity:
/**
* @param File|UploadedFile|null $imageFile
*
* @return $this
*/
public function setImageFile(File $imageFile = null)
{
$this->imageFile = $imageFile;
dump($imageFile);
if ($imageFile instanceof UploadedFile) {
$this->setFileSize($imageFile->getClientSize());
$this->setMimeType($imageFile->getClientMimeType());
$this->setOriginalName($imageFile->getClientOriginalName());
$this->updatedAt = new \DateTime();
}
return $this;
}
在if条件下转储时,它什么都不做,所以显然它不会将$ imageFile识别为UploadedFile的一个实例。但是,在此之前进行转储时(如在复制的代码中),它会转储以下信息:
UploadedFile {#14 ▼
-test: false
-originalName: "Route.png"
-mimeType: "image/png"
-size: 13218
-error: 0
path: "/tmp"
filename: "phpQhWrTd"
basename: "phpQhWrTd"
pathname: "/tmp/phpQhWrTd"
extension: ""
realPath: "/tmp/phpQhWrTd"
aTime: 2018-02-05 19:03:12
mTime: 2018-02-05 19:03:12
cTime: 2018-02-05 19:03:12
inode: 311536
size: 13218
perms: 0100600
owner: 1001
group: 33
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
显然它来自&#34; UploadedFile&#34;。有什么想法吗?
我试过的是在我的控制器中转储:
public function uploadAction(Request $request, $id){
$repository = $this->getDoctrine()->getRepository('AppBundle:Image');
$em = $this->getDoctrine ()->getManager ();
$image = $repository->findOneById($id);
dump($image);
$form = $this->createForm(UploadImageType::class, $image);
$form->handleRequest($request);
if ($form->isValid() && $form->isValid() ) {
dump($image->getImageName());
$em->flush();
return $this->redirectToRoute('index');
}
return $this->render('AppBundle:Image:upload.html.twig', array(
'form' => $form->createView(),
'image' => $image,
));
}
在 imageFile Setter 中进行了转储,我意识到,我在控制器中的转储包含&#34; old&#34; imageName,例如名称A但是Setter包含&#34; new&#34;图像名称(来自应该替换旧图像的图像),实际上是正确的图像名称。但它永远不会更新。
答案 0 :(得分:0)
这不是您获得的非托管实体错误的答案。
为了确保图片正确更新,您需要在您的实体中使用这样的方法:
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/** @var \DateTime|null */
protected $updatedAt;
/**
* @param File|UploadedFile|null $file
*
* @return $this
*/
public function setFile(File $file = null)
{
$this->file = $file;
if ($file instanceof UploadedFile) {
$this->setFileSize($file->getClientSize());
$this->setMimeType($file->getClientMimeType());
$this->setOriginalName($file->getClientOriginalName());
$this->updatedAt = new \DateTime();
}
return $this;
}