symfony多个上传vichuploadbundle

时间:2017-08-16 23:48:53

标签: php symfony

我正在使用vichuploadbundle在symfony中寻找多个上传。我也有工作上传者但仍然只有一个文件。我找不到解决问题的答案。我也尝试了许多教程,但没有任何方法可以帮助我。在他们的文档中,我无法找到答案。我该怎么办?

错误:

Expected argument of type "Symfony\Component\HttpFoundation\File\File", "array" given

我的实体:

 /**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class Product
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=50, nullable=true)
     * @Assert\NotBlank()
     * @Assert\Length(
     *     min=5,
     *     minMessage="Title is too short!",
     *     max=50,
     *     maxMessage="Title is too long!"
     * )
     */
    private $title;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
     * @ORM\JoinColumn(nullable=false)
     */
    private $author;

    /**
     * @ORM\Column(type="string", length=150, nullable=true)
     * @Assert\NotBlank()
     * @Assert\Length(
     *     min=5,
     *     minMessage="Perex is too short!",
     *     max=100,
     *     maxMessage="Perex is too long!"
     * )
     */
    private $perex;

    /**
     * @ORM\Column(type="text", length=500, nullable=true)
     * @Assert\NotBlank()
     */
    private $text;

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductPicture", mappedBy="product", cascade={"all"}, orphanRemoval=true)
     */
    private $pictures;

    public function __construct()
    {
        $this->pictures = new ArrayCollection();
    }

    /**
     * @return ArrayCollection
     */
    public function getPictures()
    {
        return $this->pictures;
    }

    /**
     * @param ArrayCollection $pictures
     */
    public function setPictures($pictures)
    {
        $this->pictures = $pictures;
    }

    public function getAttachPictures()
    {
        return null;
    }

    public function setAttachPictures(array $files=array())
    {
        if (!$files) return [];
        foreach ($files as $file) {
            if (!$file) return [];
            $this->attachPicture($file);
        }
        return [];
    }

    public function attachPicture(UploadedFile $file=null)
    {
        if (!$file) {
            return;
        }
        $picture = new ProductPicture();
        $picture->setImageFile($file);
        $this->addPicture($picture);
    }

    public function addPicture(ProductPicture $picture)
    {
        $picture->setProduct($this);
        $this->pictures->add($picture);
    }

    public function removePicture(ProductPicture $picture)
    {
        $picture->setProduct(null);
        $this->pictures->removeElement($picture);
    }
}

ProductPicture:

/**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class ProductPicture
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var Product
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Product", inversedBy="pictures")
     */
    private $product;

    /**
     *
     * @Vich\UploadableField(mapping="product_image", fileNameProperty="imageName", size="imageSize")
     * @Assert\File(
     *     maxSize = "1024k",
     *     mimeTypes = {"image/png", "image/jpeg", "image/jpg"},
     *     mimeTypesMessage = "Please upload a valid valid IMAGE"
     * )
     *
     * @var File
     */
    private $imageFile;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     *
     * @var array
     */
    private $imageName;

    /**
     *
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
     *
     * @return Product
     */
    public function setImageFile(File $image = null)
    {
        $this->imageFile = $image;
    }

    public function getImageFile()
    {
        return $this->imageFile;
    }

    public function setProduct(Product $product)
    {
        $this->product = $product;
    }

    public function getProduct()
    {
        return $this->product;
    }

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

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

    /**
     * @return array
     */
    public function getImageName()
    {
        return $this->imageName;
    }

    /**
     * @param array $imageName
     */
    public function setImageName($imageName)
    {
        $this->imageName = $imageName;
    }

}

形式:

class ProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('perex')
            ->add('text')
            ->add('attachPictures', FileType::class, ['multiple'=>true, 'required'=>false])
        ;
    }

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

3 个答案:

答案 0 :(得分:0)

我无法帮助您使用此上传工具包,但我可以用更简单的方式向您展示它在我的案例中的工作方式(使用简单的请求,而不是一些花哨的捆绑包)

这里 https://gist.github.com/poznet/e3955a48fea01d8640dafbd966c53a83

你有

  • 在视图中显示
  • 控制器代码
  • 在服务实体中导入的特征

这个特性有点乱(没有附带大小/类型检查等),但它有效。

如果您有任何问题可以随意提出。

PS在你的情况下,如果你上传多个文件你得到数组,而不是文件类:D

答案 1 :(得分:0)

您应该将文件部件构建为实体

balance > amount

在您的产品实体中......

/**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class ProductPicture
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var Product
     * @ORM\ManyToOne(targetEntity="path\to\your\entity\Product", inversedBy="pictures")
     */
    private $product;

    /**
     *
     * @Vich\UploadableField(mapping="product_image", fileNameProperty="imageName", size="imageSize")
     * @Assert\File(
     *     maxSize = "1024k",
     *     mimeTypes = {"image/png", "image/jpeg", "image/jpg"},
     *     mimeTypesMessage = "Please upload a valid valid IMAGE"
     * )
     *
     * @var File
     */
    private $imageFile;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     *
     * @var array
     */
    private $imageName;

    /**
     *
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
     *
     * @return Product
     */
    public function setImageFile(File $image = null)
    {
        $this->imageFile = $image;
    }

    public function getImageFile()
    {
         return $this->imageFile;
    }

    public function setProduct(Product $product)
    {
        $this->product = $product;
    }

    public function getProduct()
    {
         return $this->product;
    } 
}

最后以表格形式使用......

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="path\to\your\entity\ProductPicture", mappedBy="product", cascade={"all"}, orphanRemoval=true)
     */
    private $pictures;

    public function __construct()
    {
        $this->pictures = new ArrayCollection();
    }

    /**
     * @return ArrayCollection
     */
    public function getPictures()
    {
        return $this->pictures;
    }

    /**
     * @param ArrayCollection $pictures
     */
    public function setPictures($pictures)
    {
        $this->pictures = $pictures;
    }

    public function getAttachPictures()
    {
        return null;
    }

    public function setAttachPictures(array $files=array())
    {
        if (!$files) return [];
        foreach ($files as $file) {
            if (!$file) return [];
            $this->attachPicture($file);
        }
        return [];
    }

    public function attachPicture(UploadedFile $file=null)
    {
        if (!$file) {
            return;
        }
        $picture = new ProductPicture();
        $picture->setImageFile($file);
        $this->addPicture($picture);
    }

    public function addPicture(ProductPicture $picture)
    {
        $picture->setProduct($this);
        $this->pictures->add($picture);
    }

    public function removePicture(ProductPicture $picture)
    {
       $picture->setProduct(null);
       $this->pictures->removeElement($picture);
   }

答案 2 :(得分:0)

Symfony 4 工作解决方案。

非常简单。整理您的实体,创建表单并form transformer

// src/Entity/Product.php
 /**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class Product
{
    ...

    /**
     * @var Collection|ProductPicture[]
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductPicture", mappedBy="product", cascade={"persist", "remove"}, orphanRemoval=true)
     */
    private $pictures;

    public function __construct()
    {
        $this->pictures = new ArrayCollection();
    }

    /**
     * @return Collection|ProductPicture[]
     */
    public function getPictures(): Collection
    {
        return $this->pictures;
    }

    public function addPicture(ProductPicture $picture): self
    {
        if (!$this->pictures->contains($picture) {
            $this->pictures->add($picture);
            $picture->setProduct($this);
        }

        return $this;
    }

    public function removePicture(ProductPicture $picture): self
    {
        if ($this->pictures->contains($picture) {
            $this->pictures->removeElement($picture);
            if ($picture->getProduct() === $this) {
                $picture->setProduct(null);
            }
        }

        return $this;
    }

    ...
}
// src/Entity/ProductPicture.php
/**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class ProductPicture
{
    ...

    /**
     * @var Product
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Product", inversedBy="pictures")
     * @ORM\JoinColumn(nullable=false)
     */
    private $product;

    /**
     *
     * @Vich\UploadableField(mapping="product_image", fileNameProperty="imageName", size="imageSize")
     * @Assert\File(
     *     maxSize = "1024k",
     *     mimeTypes = {"image/png", "image/jpeg", "image/jpg"},
     *     mimeTypesMessage = "Please upload a valid valid IMAGE"
     * )
     *
     * @var File
     */
    private $imageFile;

    ...

    /**
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
     *
     * @return Product
     */
    public function setImageFile(?File $image = null)
    {
        $this->imageFile = $image;

        if (null !== $image) {
            // 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->updatedAt = new DateTimeImmutable();
        }
    }

    public function getImageFile()
    {
        return $this->imageFile;
    }

    public function setProduct(Product $product)
    {
        $this->product = $product;
    }

    public function getProduct()
    {
        return $this->product;
    }

    ...
}

然后您需要创建简单的ProductType表单:

// src/Form/ProductForm.php
class PictureType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add($builder->create(
                'pictures',
                FileType::class,
                [
                    'required' => false,
                    'multiple' => true,
                ]
            )->addModelTransformer(new FilesToPicturesTransformer()))
            ->add(...);
    }

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

和FilesToPicturesTransformer(数据转换器):

// src/Form/FilesToPicturesTransformer.php
class FilesToPicturesTransformer implements DataTransformerInterface
{
    /**
     * {@inheritdoc}
     */
    public function transform($value): void
    {
        // don't need this if you build API
    }

    /**
     * {@inheritdoc}
     */
    public function reverseTransform($value): ArrayCollection
    {
        $pictures = new ArrayCollection();

        foreach ($value as $file) {
            $picture = (new ProductPicture())
                ->setImageFile($file);
            if (!$pictures->contains($picture)) {
                $pictures->add($picture);
            }
        }

        return $pictures;
    }
}