Php symfony多重上传vichuploadbundle

Php symfony多重上传vichuploadbundle,php,symfony,Php,Symfony,我正在寻找使用vichuploadbundle在symfony中进行多次上传。我也有工作上传,但仍然只有一个文件。我找不到解决问题的答案。我也试过很多教程,但都不管用。在他们的文件中我找不到答案。我该怎么办 错误: Expected argument of type "Symfony\Component\HttpFoundation\File\File", "array" given 我的实体: /** * @ORM\Entity * @Vich\Uploadable */ class

我正在寻找使用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);
    }
}
产品图片:

/**
 * @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;
    }

}
表格:


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

这里

你有

  • 视野中的形式
  • 控制器代码
  • 在服务实体中导入的特征
这个特性有点混乱(没有附件尺寸/类型检查等),但它可以工作

如果您有任何问题,请随时提问


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

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

/**
 * @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);
   }
最后在形式上使用

->add('attachPictures', FileType::class, ['multiple'=>true, 'required'=>false])

Symfony 4工作解决方案

非常简单。只需整理实体,创建表单和

然后您需要创建简单的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,
        ]);
    }

和文件主题图片转换器(数据转换器):


可捕获的致命错误:传递给AppBundle\Entity\Product::attachPicture()的参数1必须是AppBundle\Entity\UploadedFile的实例,Symfony\Component\HttpFoundation\File\UploadedFile的实例,因为我实际修复了此错误,但我收到错误500检查您在产品实体顶部使用的不是
use-AppBundle\entity\UploadedFile
,它必须是
use-Symfony\Component\HttpFoundation\File\UploadedFile
您能提供Symfony工具栏的跟踪错误吗?看起来像是表单问题。。。尝试更改
->add('attachPictures','file',['multiple'=>true,'required'=>false])
以添加('attachPictures',FileType::class,['multiple'=>true,'required'=>false])或
->add('attachPictures',VichFileType::class,['multiple'=>true,'required'=>false])
// 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;
    }

    ...
}
// 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,
        ]);
    }

// 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;
    }
}