1

我几天都没有找到解决我的问题的解决方案。我想在创建帖子时上传多张图片。我的 Post 实体与 Image Entity 具有 OneToMany 关系。我在我的 PostType 中使用嵌入式表单。它是 ImageType::class 的 CollectionType。为了管理我的上传功能,我编写了一个名为 ImageUploadListener 的事件监听器,它注入了名为 FileUploader 的自定义服务。

此侦听器在处理 preUpdate 和 prePersist 事件时调用 uploadFile 函数。此函数从我的 FileUploader 调用我的上传函数,以将图像/文件...移动到目标目录并返回文件名。

之后,我尝试实例化一个图像实体并设置适当的数据。但它不起作用,似乎只有一个文件被正确存储,但在我的数据库中还有一个不需要的额外条目。(在我的图像表中,对于上传的一张图像,我有一个 id 为 1 的条目,例如,post_id 设置为 NULL,文件字段设置为 /tmp/random number)。

拜托,你能帮我吗?

发布实体

namespace UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Post
 *
 * @ORM\Table(name="post")
 * @ORM\Entity(repositoryClass="UserBundle\Repository\PostRepository")
 */
class Post
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Title", type="string", length=255)
     */
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="Content", type="text")
     */
    private $content;


    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="posts")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
    */
    private $user;

    /**
     * @ORM\OneToMany(targetEntity="Image", mappedBy="post", cascade={"persist", "remove"})
     */
    private $images;

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     *
     * @return Post
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set content
     *
     * @param string $content
     *
     * @return Post
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set post
     *
     * @param \
     *
     * @return Post
     */
    public function setUser($user)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get post
     *
     * @return \?
     */
    public function getUser()
    {
        return $this->user;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->images = new ArrayCollection();
    }

    /**
     * Add image
     *
     * @param \UserBundle\Entity\Image $image
     *
     * @return Post
     */
    public function addImage(\UserBundle\Entity\Image $image)
    {
        $this->images[] = $image;

        return $this;
    }

    /**
     * Remove image
     *
     * @param \UserBundle\Entity\Image $image
     */
    public function removeImage(\UserBundle\Entity\Image $image)
    {
        $this->images->removeElement($image);
    }

    /**
     * Get images
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getImages()
    {
        return $this->images;
    }
}

图像实体

namespace UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="UserBundle\Entity\ImageRepository")
 */
class Image
{
  /**
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;


  /**
   * @ORM\Column(type="string", nullable=true)
   */
  private $file;

  public function setFile($file)
  {
      $this->file = $file;
      return $this;
  }

  public function getFile()
  {
      return $this->file;
  }


  /**
   * @ORM\ManyToOne(targetEntity="Post", inversedBy="images")
   * @ORM\JoinColumn(name="post_id", referencedColumnName="id")
  */
  private $post;


  /**
   * Get id
   *
   * @return integer
   */
  public function getId()
  {
      return $this->id;
  }


  /**
   * Set post
   *
   * @param \UserBundle\Entity\Post $post
   *
   * @return Image
   */
  public function setPost(\UserBundle\Entity\Post $post = null)
  {
      $this->post = $post;

      return $this;
  }

  /**
   * Get post
   *
   * @return \UserBundle\Entity\Post
   */
  public function getPost()
  {
      return $this->post;
  }
}

邮政类型

namespace UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
//use Ivory\CKEditorBundle\Form\Type\CKEditorType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use UserBundle\Entity\Post;


class PostType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('content')
            ->add('images', CollectionType::class, array (
                'entry_type' => ImageType::class,
                'entry_options' => array('label' => false),
                'allow_add' => true,
                'allow_delete' => true
            ))
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            //'data_class' => 'UserBundle\Entity\Post',
            'data_class' => Post::class,
            //'csrf_protection' => false
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'userbundle_post';
    }


}

ImageType 命名空间 UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use UserBundle\Entity\Image;

class ImageType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', FileType::class, [
                'required' => false,
                'data_class' => null,
            ])
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Image::class,
            //'csrf_protection' => false
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'userbundle_image';
    }
}

编辑:ImageUploadListener

//src/UserBundle/EventListener/ImageUploadListener.php
namespace UserBundle\EventListener;

use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\File\File;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;

use UserBundle\Entity\User;
use UserBundle\Entity\Post;
use UserBundle\Entity\Image;

use UserBundle\Service\FileUploader;


class ImageUploadListener
{
    private $uploader;


    public function __construct(FileUploader $uploader)
    {
        $this->uploader = $uploader;
    }

    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $this->uploadFile($entity);
    }

    public function preUpdate(PreUpdateEventArgs $args)
    {
        $entity = $args->getEntity();
        $this->uploadFile($entity);
    }

    private function uploadFile($entity)
    {
        if ($entity instanceof Post) {

            $post = $entity;
            $images = $post->getImages();
            foreach ($images as $image) {
                if ($image->getFile() instanceof UploadedFile) {
                    $imageName = $this->uploader->upload($image->getFile());

                    // to avoid persisting FileObject in DB
                    $post->removeImage($image);

                    $postImage = new Image();
                    $postImage->setFile($imageName);
                    $postImage->setPost($post);
                    $post->addImage($postImage);
                }
            }
        }
        return;
    }
}

文件上传器

namespace UserBundle\Service;

use Symfony\Component\HttpFoundation\File\UploadedFile;

class FileUploader
{
    private $targetDir;
    public function __construct($targetDir)
    {
        $this->targetDir = $targetDir;
    }

    public function upload(UploadedFile $file)
    {

        $fileName = md5(uniqid()).'.'.$file->guessExtension();
        $file->move($this->getTargetDir(), $fileName);
        return $fileName;
    }

    public function getTargetDir()
    {
        return $this->targetDir;
    }
}
4

0 回答 0