VichUploader:图片更新失效

时间:2018-02-01 20:53:29

标签: image symfony vichuploaderbundle

我的主页横幅上有四张图片,我希望能够使用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;图像名称(来自应该替换旧图像的图像),实际上是正确的图像名称。但它永远不会更新。

1 个答案:

答案 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;
}