1
votes

How to upload with form collection, ZF2 and Doctrine2?

When I upload an image file, entity Image method setFileName($value) receives input array $_FILE('name'=>'image.jpg', 'tmp_name'=>....).

This is my code:

Entity Image

namespace Application\Entity;

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

    /**
     * @var string
     * @ORM\Column(type="string")
     */
    protected $filename;


    /**
     * @ORM\ManyToOne(targetEntity="Application\Entity\Product", inversedBy="images")
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $product;
...

    public function getFileName()
    {
        return $this->filename;
    }


    public function setFileName($name)
    {

        $this->filename = $name;

    }

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


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

}

Entity Product

namespace Application\Entity;

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

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */
class Product
{
    /**
     * @var int
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     *
     */
    protected $id;

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

    /**
     * @ORM\OneToMany(targetEntity="Application\Entity\Image", 
                      mappedBy="product", cascade={"persist"})
     */
    protected $images;

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

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

    /**
     * Set id.
     *
     * @param int $id
     *
     * @return void
     */
    public function setId($id)
    {
        $this->id = (int) $id;
    }

    ....

    /**
     * Add images
     *
     * @param Collection $image
     */
    public function addImages($images)
    {
        foreach ($images as $image)
        {
            $tag->setProduct($this);
            $this->images->add($image);
        }
    }

    /**
     * Remove images
     *
     * @param \Application\Entity\Image $images
     */
    public function removeImages($images)
    {
        foreach ($images as $image)
        {
            $tag->setProduct(null);
            $this->images->removeElement($image);
        }
    }

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

}

Fieldset Image

class ImageFieldset extends Fieldset implements InputFilterProviderInterface
{

    public function __construct(ObjectManager $objectManager)
    {
        parent::__construct('product-image');

        $this->setHydrator(new DoctrineHydrator($objectManager, 
                                                'Application\Entity\Image'))
             ->setObject(new Image());

        $this->add(array(
                    'name' => 'filename',
                    'type' => 'Zend\Form\Element\File',
                    'options' => array(
                        'label' => 'Photo Upload',
                        'label_attributes' => array(
                            'class' => 'form-label'
                        ),
                        'multiple' => true,
                        'id' => 'filename'
                    )
                )
        );

    } 

Form Product

class ProductForm extends Form
{

    public function __construct(ObjectManager $objectManager, $name)
    {
        parent::__construct($name);

        $this->setAttribute('enctype', 'multipart/form-data');
        $this->setAttribute('method', 'post')
                ->setHydrator(new DoctrineHydrator($objectManager, 
                                                  'Application\Entity\Product'));

        $imageFieldset = new ImageFieldset($objectManager);
        $imageFieldset->setName("images");
        $this->add(array(
            'type' => 'Zend\Form\Element\Collection',
            'name' => 'images',
            'options' => array(
                'allow_add' => true,
                'allow_remove' => false,
                'count' => 1,
                'target_element' => $imageFieldset
            )
        ));

      $this->setValidationGroup(array(
            'name',
            'images',
            ...
        ));
}

Product Controller

class ProductController extends AbstractActionController
{
    public function addAction()
    {
       $em = $this->getEntityManager();
       $request = $this->getRequest();

       $form = new ProductForm($em, 'product');
       $product = new Product();

       $form->bind($product);

       if ($request->isPost()):
          $dataForm = array_merge_recursive(
                $request->getPost()->toArray(),
                $request->getFiles()->toArray()
            );
          $form->setData($dataForm);
          if ($form->isValid()):
              $em->persist($product);
              $em->flush(); 
          endif;
       endif;
    }
}

The closest thing I've found has been in Symfony2: Uploading images using Form Collections and Doctrine in Symfony2

1
Hello! What is the problem and did you try to write some code?edigu

1 Answers

1
votes

Usually I do something like that:

public function setFileName($filename)
{
    if (is_array($filename) && isset($filename['tmp_name'])) {
        $filename = $filename['tmp_name'];
    }

    $this->fileName = $filename;
}