使用symfony上传多个图像,无需额外的捆绑

时间:2015-04-10 15:42:46

标签: php image symfony file-upload multiple-file-upload

当我尝试将多个图像上传到数据库时,我遇到了问题。 我已经阅读了symfony文档,我每次都可以上传一张图片。 我也读过

http://symfony.com/doc/current/cookbook/form/form_collections.html

到目前为止,我完全理解上传ONE IMAGE的过程,但是当您需要上传多张图片时会发生什么? 这是我的情况,我有一个Store实体和一个StorePhoto实体,一个商店包含与StorePhoto的OneToMany关系(变量commerce_photos),(我正在为商店开发某种图像库。) 我的想法是一次上传多张图片,我的意思是选择多个文件并上传它们。 这就是我所做的

我的商店实体

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
* @ORM\Entity
* @ORM\Table(name="store")
* 
*/

class Store{

    /**
    * @ORM\Id
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
    */
    protected $name;

    /**
    * @ORM\OneToOne(targetEntity="StorePhoto")
    */
    protected $photo;

    /**
     * @ORM\OneToMany(targetEntity="StorePhoto", mappedBy="store_photo")
     */ 
    protected $commerce_photos;

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


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

    /**
     * Set name
     *
     * @param string $name
     * @return Store
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Add commerce_photos
     *
     * @param \AppBundle\Entity\StorePhoto $commercePhotos
     * @return Store
     */
    public function addCommercePhotos(\AppBundle\Entity\StorePhoto $commercePhotos)
    {
        $this->commerce_photos[] = $commercePhotos;

        return $this;
    }

    /**
     * Remove commerce_photos
     *
     * @param \AppBundle\Entity\StorePhoto $commercePhotos
     */
    public function removeCommercePhotos(\AppBundle\Entity\StorePhoto $commercePhotos)
    {
        $this->commerce_photos->removeElement($commercePhotos);
    }

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

我的StorePhoto实体

<?php

namespace AppBundle\Entity;

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


/**
* @ORM\Entity
* @ORM\Table(name="store_photo")
*/

class StorePhoto{

    /**
    * @ORM\Id
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    /**
    * @ORM\Column(type="string", length=255)
    */
    protected $imageName;

    /**
    * @ORM\Column(type="string", length=255,nullable=false)
    */
    protected $path;

    /**
    * @ORM\ManyToOne(targetEntity="Store", inversedBy="commerce_photos")
    */
    protected $store_photo;

    /**
    * @Assert\Image
    (mimeTypes = {"image/jpg", "image/jpeg", "image/gif", "image/png"}, 
     mimeTypesMessage = "Solo acepta imagenes en formato JPG, GIF ou PNG.",
     maxSize="5000k")   
    */
    private $imageFile;

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

    /**
     * Get file.
     *
     * @return UploadedFile
     */
    public function getImageFile()
    {
        return $this->imageFile;   
    }
    /**
     * Sets file.
     *
     * @param UploadedFile $imageFile
     */
    public function setImageFile(UploadedFile $file = null)
    {
        $this->imageFile = $file;
    }
    /**
     * Set imageName
     *
     * @param string $imageName
     * @return StorePhoto
     */
    public function setImageName($imageName)
    {
        $this->imageName = $imageName;

        return $this;
    }

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

    /**
     * Set store_photo
     *
     * @param \AppBundle\Entity\Store $storePhoto
     * @return StorePhoto
     */
    public function setStorePhoto(\AppBundle\Entity\Store $storePhoto = null)
    {
        $this->store_photo = $storePhoto;

        return $this;
    }

    /**
     * Get store_photo
     *
     * @return \AppBundle\Entity\Store 
     */
    public function getStorePhoto()
    {
        return $this->store_photo;
    }
    public function getAbsolutePath()
    {
        return null === $this->path
            ? null
            : $this->getUploadRootDir().'/'.$this->path;
    }
    public function getWebPath()
    {
        return null === $this->path
            ? null
            : $this->getUploadDir().'/'.$this->path;
    }
    protected function getUploadRootDir()
    {
        //the absolute directory where uploaded documents should be saved
        return __DIR__.'/../../../../web/images'.$this->getUploadDir();

    }
    protected function getUploadDir()
    {
        //get rid of the __DIR__ so it doesn't screw up 
        //when displaying uploaded doc/image in the view
        return 'uploads/documents';

    }
    public function upload()
    {
        //the file property can be empty if the field is not required

        if(null === $this->getImageFile())
        {
            return;
        }
        //use the original file name here but you should
        //sanitaze it at least to avoid any security issues    

        //move takes the target directory and then the target filename to move to.
        $this->getImageFile()->move(
            $this->getUploadRootDir(), $this->getImageFile()->getClientOriginalName()
        );

        //set the path property to the filename where you've saved the file
        $this->path = $this->getImageFile()->getClientOriginalName();
        //clean up the file property as you won't need it anymore...
        $this->imageFile = null;

    }

}

我的控制器

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use AppBundle\Forms\Type\FileUploadType;
use Symfony\Component\HttpFoundation\Request;   
use AppBundle\Entity\StorePhoto;
use AppBundle\Entity\Store;
use Symfony\Component\HttpFoundation\Response;
use AppBundle\Forms\Type\MultipleFileUploadType;


class DefaultController extends Controller
{

   public function multipleFileUploadAction(Request $request)
    {
        $store = new Store();

        $store->setName('Test01');

        $store->addCommercePhotos(new StorePhoto());

        $form = $this->createForm(new MultipleFileUploadType(),$store);

        $form->handleRequest($request);

        if($form->isValid())
        {
            $em = $this->getDoctrine()->getManager();

            $em->persist($store);

            $em->flush();

            return new Response('200 OK...');
        }

        return $this->render('Forms/FileUpload.html.twig',array('form'=>$form->createView()));


    }
}

我的表单现在,FileUploadType和MultipleFileUploadType

<?php
namespace AppBundle\Forms\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FileUploadType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('imageName', 'text');
        $builder->add('imageFile', 'file',
                     array('multiple'=>'multiple'));
      //  $builder->add('Save', 'submit');

    }
    public function getName()
    {
        return "storePhoto";

    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
           'data_class' => 'AppBundle\Entity\StorePhoto',
        ));


    }
}

?>

<?php
namespace AppBundle\Forms\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use AppBundle\Forms\Type\FileUploadType;

class MultipleFileUploadType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name','text');
        $builder->add('commerce_photos', 'collection',array(
        'type' => new FileUploadType()));
        $builder->add('Save', 'submit');

    }
    public function getName()
    {
        return "MultipleFileUpload";

    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Store',
        ));
    }
}

?>

这是所有代码,我不知道我是否在这里遗漏了一些东西。 我需要做的是显示对话框,选择几个图像,然后保存它们。 在这种情况下,在控制器中我写了这一行

    $store = new Store();

    $store->setName('Test01');

    $store->addCommercePhotos(new StorePhoto());

在这种情况下,当我渲染表单时,它会显示一个对话框,只允许我选择一个文件。 如果我删除第三行,addCommerce ...它只显示标签为commercePhotos。

提前致谢!

1 个答案:

答案 0 :(得分:0)

在你没有为field commerce_photos设置值之前,Symfony会将其识别为空。对于空字段,它不会呈现输入元素。所以你需要自己设置一些虚拟值或渲染字段:

{{ form_label(form.imageFile) }}
<input type="file" name="{{ form.imageFile.vars.fullName }}[]" class="file-upload" />

方括号对于使Symfony处理多个值非常重要。要使表单一次接受多个文件,您可能需要一些这样的jquery:

$('.file-upload').on('change', function (event) {
  $(event.currentTarget).after('<input type="file" name="{{ form.imageFile.vars.fullName }}[]" class="file-upload" />');
});