2
votes

UPDATE: I just work until version 2.2.5 of ZF2 if I upgrade to 2.2.6 on, the item is not displayed on the form.

  • ZF2 2.3.1
  • PHP 5.4.4
  • Doctrine2: Master

I have a problem with the bind () the form. When I try to show an element of the Zend\Form\Collection fieldset appears empty.

I have reviewed the tutorial Doctrine Hydrator but I can not fix it.

The relationship between the entities is quite simple:

  • Product (OneToMany) $images
  • Image (ManyToOne) $product

This only happens when I add a new product, if I edit a product with image (action edit), FormCollection element shown on the form.

Product Entity

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=false, nullable=true)
     */
    protected $name;

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

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

    public function addImages(Collection $images)
    {
        foreach ($images as $image)
        {
            $image->setProduct($this);
            $this->images->add($image);
        }
    }

    public function removeImages(Collection $images)
    {
        foreach ($images as $image)
        {
            $image->setProduct(null);
            $this->images->removeElement($image);
        }
    }

    public function getImages()
    {
        return $this->images;
    }

}

Image Entity

class Image
{
    protected $id;

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

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

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

Product Form

class ProductForm extends Form implements InputFilterProviderInterface
{

    public function __construct($sl)
    {
        $objectManager = $sl->get('Doctrine\ORM\EntityManager');

        parent::__construct('product-form');

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

        // Add the user fieldset, and set it as the base fieldset
        $productFieldset = new ProductFieldset($sl);
        $productFieldset->setName('product');
        $productFieldset->setUseAsBaseFieldset(true);
        $this->add($productFieldset);

        $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                'type' => 'submit',
                'value' => 'Go',
                'id' => 'submitbutton',
                'class' => 'btn btn-primary'
            )
        ));


        $this->setValidationGroup(array(
            'product',
        ));
    }

Product Fieldset

class ProductFieldset extends Fieldset implements InputFilterProviderInterface
{

    public function __construct($sl)
    {
        $objectManager = $sl->get('Doctrine\ORM\EntityManager');

        parent::__construct('product');

        $this->setHydrator(new DoctrineHydrator($objectManager))
             ->setObject(new Product());


        $this->add(array(
            'name' => 'id',
            'type' => 'Zend\Form\Element\Hidden'
        ));

        $this->add(array(
            'type' => 'Zend\Form\Element\Collection',
            'name' => 'images',
            'options' => array(
                'count' => 1,
                'target_element' => new ImageFieldset($objectManager)
            )
        ));
   }
}

Image Fieldset

class ImageFieldset extends Fieldset implements InputFilterProviderInterface
{

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


            $this->setHydrator(new DoctrineHydrator($objectManager))
                 ->setObject(new Image());

            $this->add(array(
                        'name' => 'id',
                        'type' => 'Zend\Form\Element\Hidden'
                        )
            );

            $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'
                        )
                    )
            );
        }

        public function getInputFilterSpecification()
            {
                return array(
                   'id' => array(
                        'required' => false
                    ),
                   'filename' => array(
                        'required'    => true,
                    )
                );
        }
    }

Controller

public function addAction()
{

        $sl = $this->getServiceLocator();

        $form = new ProductForm($sl);

        $product = new Product();

        $form->bind($product);

        if ($request->isPost()):
              ....
        endif;

        return array('form' => $form);

}
2
Not sure if its a copy paste issue, however your product entity is missing a protected $images; property.AlexP
Right, I forgot to paste protected $images;.supernacho

2 Answers

0
votes

Maybe you are facing this issue: BC break in forms between 2.3.0 and 2.3.1

There's been a BC break in Zend\Form between 2.3.0 and 2.3.1, we just upgraded and stumbled into it. We get instances of our Forms through the FormElementManager as we use custom form elements, the site has been working with <= 2.3.0 but after the 2.3.1 upgrade when we get instances of Forms they no longer have any elements attached.

Some general changes when using the FormElementManager: Creating custom elements

To use custom elements with the FormElementManager needs a bit more work and most likely a change in how you write and use your forms.
0
votes

Maybe this tutorial can help - it's pretty up to date: Inject DoctrineORM EntityManager in ZF2 Form

It uses the formElementManager and the objectManager awareness.

It is important to add the elements inside the init() method, not the constructor.

Please also have a look at the comments where Michael states:

I just found out that in the latest version of ZF2 (I have 2.2.5 here) it´s not necessary any more to pass the entityManager via the module config. You only have to implement the “ObjectManagerAwareInterface” in the form class (as well as the required getter + setter) and you will have access via $this->getObjetManager().