Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ZF2 Form sets all select options as selected on bind

I have a problem with my ZF2 form element (select). When i bind my doctrine entity to this form, all my select options get the selected attribute instead of just the one that should. The entity just got a connected object and the Hydrator is set in the for aswell.

Here is some of my code. Hope i just missed something small.

AddressEntity.php

<?php

namespace Application\Entity;

use Doctrine\ORM\Mapping as ORM;
use ZF2Core\Entity\AbstractEntity;

/**
 * @ORM\Entity
 * @ORM\Table(name="`address`")
 */
class Address extends AbstractEntity
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="bigint", options={"unsigned":true})
     */
    protected $addressId;

    /**
     * @ORM\ManyToOne(targetEntity="SNOrganisation\Entity\Organisation", inversedBy="organisationId")
     * @ORM\JoinColumn(name="organisationId", referencedColumnName="organisationId", nullable=false)
     */
    protected $organisation;

    /**
     * @ORM\ManyToOne(targetEntity="AddressType")
     * @ORM\JoinColumn(name="addressTypeId", referencedColumnName="addressTypeId", nullable=false)
     */
    protected $addressType;

    /** @ORM\Column(type="string", nullable=true) */
    protected $otys;

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

    /** @ORM\Column(type="string", nullable=true) */
    protected $postalcode;

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

    /** @ORM\Column(type="string", nullable=true) */
    protected $email;

    /**
     * @ORM\ManyToOne(targetEntity="ZF2Country\Entity\Country")
     * @ORM\JoinColumn(name="countryId", referencedColumnName="countryId", nullable=false)
     */
    protected $country;

    /** @ORM\Column(type="datetime") */
    protected $created;

    /** @ORM\Column(type="datetime", nullable=true) */
    protected $deleted;

    public function getAddressId()
    {
        return $this->addressId;
    }

    public function getOrganisation()
    {
        return $this->organisation;
    }

    public function getAddressType()
    {
        return $this->addressType;
    }

    public function getOtys()
    {
        return $this->otys;
    }

    public function getAddress()
    {
        return $this->address;
    }

    public function getPostalcode()
    {
        return $this->postalcode;
    }

    public function getCity()
    {
        return $this->city;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function getCreated()
    {
        return $this->created;
    }

    public function getDeleted()
    {
        return $this->deleted;
    }

    public function setAddressId($addressId)
    {
        $this->addressId = $addressId;
        return $this;
    }

    public function setOrganisation($organisation)
    {
        $this->organisation = $organisation;
        return $this;
    }

    public function setAddressType($addressType)
    {
        $this->addressType = $addressType;
        return $this;
    }

    public function setOtys($otys)
    {
        $this->otys = $otys;
        return $this;
    }

    public function setAddress($address)
    {
        $this->address = $address;
        return $this;
    }

    public function setPostalcode($postalcode)
    {
        $this->postalcode = $postalcode;
        return $this;
    }

    public function setCity($city)
    {
        $this->city = $city;
        return $this;
    }

    public function setEmail($email)
    {
        $this->email = $email;
        return $this;
    }

    public function setCreated($created)
    {
        $this->created = $created;
        return $this;
    }

    public function setDeleted($deleted)
    {
        $this->deleted = $deleted;
        return $this;
    }

    public function getCountry()
    {
        return $this->country;
    }

    public function setCountry($country)
    {
        $this->country = $country;
        return $this;
    }

}

AddressForm.php

<?php

namespace SNOrganisation\Form;

use Zend\Form\Form;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Application\Entity\Address;
use Zend\ServiceManager\ServiceManager;

class AddressForm extends Form
{

    public function __construct($name = null, $entityManager, ServiceManager $serviceManager)
    {
        parent::__construct($name);

        $this->setAttribute('method', 'post');
        $this->setAttribute('class', 'form-horizontal');

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

        $this->add(array(
            'name'       => 'addressType',
            'type'       => 'select',
            'options'    => array(
                'label'              => _('Type'),
                'label_attributes'   => array(
                    'class' => 'col-lg-2 control-label'
                ),
                'value_options' => $this->getAddressTypeOptions($serviceManager),
            ),
            'attributes' => array(
                'class'      => 'form-control',
            ),
        ));

        $this->add(array(
            'name'       => 'address',
            'type'       => 'text',
            'options'    => array(
                'label'              => _('Address'),
                'label_attributes'   => array(
                    'class' => 'col-lg-2 control-label'
                ),
            ),
            'attributes' => array(
                'class'          => 'form-control',
                'placeholder'    => 'Abbey Road 1',
            ),
        ));

        $this->add(array(
            'name'       => 'postalcode',
            'type'       => 'text',
            'options'    => array(
                'label'              => _('Postalcode'),
                'label_attributes'   => array(
                    'class' => 'col-lg-2 control-label'
                ),
            ),
            'attributes' => array(
                'class'      => 'form-control',
                'placeholder'    => '1234 AB',
            ),
        ));

        $this->add(array(
            'name'       => 'city',
            'type'       => 'text',
            'options'    => array(
                'label'              => _('City'),
                'label_attributes'   => array(
                    'class' => 'col-lg-2 control-label'
                ),
            ),
            'attributes' => array(
                'class'      => 'form-control',
                'placeholder'    => 'Amsterdam',
            ),
        ));

        $this->add(array(
            'name'       => 'country',
            'type'       => 'select',
            'options'    => array(
                'label'              => _('Country'),
                'label_attributes'   => array(
                    'class' => 'col-lg-2 control-label'
                ),
                'value_options' => $this->getCountryOptions($serviceManager),
            ),
            'attributes' => array(
                'class'      => 'form-control',
            ),
        ));

        $this->add(array(
            'name'       => 'email',
            'type'       => 'email',
            'options'    => array(
                'label'              => _('Email'),
                'label_attributes'   => array(
                    'class' => 'col-lg-2 control-label'
                ),
            ),
            'attributes' => array(
                'class'      => 'form-control',
                'placeholder'    => '[email protected]',
            ),
        ));
        $this->add(array(
            'name'       => 'submit',
            'type'       => 'submit',
            'options'    => array(
                'label' => _('Save'),
            ),
            'attributes' => array(
                'class' => 'btn btn-large btn-primary',
            ),
        ));
    }

    protected function getAddressTypeOptions($serviceManager)
    {
        $data = array();
        $addressTypeService = $serviceManager->get('application_service_addresstype');
        $addressTypeCollection = $addressTypeService->getAddressTypes()->getResult();

        foreach($addressTypeCollection as $addressType)
        {
            $data[$addressType->getAddressTypeId()] = $addressType->getName();
        }
        return $data;
    }

    protected function getCountryOptions($serviceManager)
    {
        $data = array();
        $countryService = $serviceManager->get('zf2country_service_country');
        $countryCollection = $countryService->getCountries()->getResult();

        foreach($countryCollection as $country)
        {
            $data[$country->getCountryId()] = $country->getName();
        }
        return $data;
    }
}

AddressController.php

<?php

namespace SNOrganisation\Controller;

use ZF2Core\Controller\AbstractController;
use Zend\View\Model\ViewModel;
use Application\Entity\Address;

class AddressController extends AbstractController
{
    public function editAction()
    {
        $organisationId = (int)$this->params()->fromRoute('id');
        $addressId = (int)$this->params()->fromRoute('addressId');
        $request = $this->getRequest();
        $address = $this->getEntityManager()->getRepository('Application\Entity\Address')->find($addressId);

        if ($address)
        {
            $addressForm = $this->getServiceLocator()->get('snorganisation_form_address');
            $addressForm->bind($address);
        }
        else
        {
            $this->resultMessenger()->addFatalMessage($this->getTranslator()->translate('The address could not be found'));
            $this->redirect()->toRoute('organisation');
        }

            return new ViewModel(array(
            'addressForm' => $addressForm,
        ));
    }
}

Entity Dump

<?php
object(Application\Entity\Address)[700]
  protected 'addressId' => string '487956' (length=6)
  protected 'organisation' => 
    object(DoctrineORMModule\Proxy\__CG__\SenetOrganisation\Entity\Organisation)[701]
      public '__initializer__' => 
        object(Closure)[583]
      public '__cloner__' => 
        object(Closure)[584]
      public '__isInitialized__' => boolean false
      protected 'organisationId' => string '412705' (length=6)
      protected 'ownerPerson' => null
      protected 'otys' => null
      protected 'name' => null
      protected 'paymentInterval' => null
      protected 'vatNumber' => null
      protected 'debtor' => null
      protected 'invoiceByEmail' => null
      protected 'active' => null
      protected 'reasonInactive' => null
      protected 'created' => null
      protected 'addressCollection' => null
      protected 'personCollection' => null
      protected 'orderCollection' => null
      protected 'serviceManager' => null
  protected 'addressType' => 
    object(DoctrineORMModule\Proxy\__CG__\Application\Entity\AddressType)[714]
      public '__initializer__' => 
        object(Closure)[704]
      public '__cloner__' => 
        object(Closure)[705]
      public '__isInitialized__' => boolean false
      protected 'addressTypeId' => string '2' (length=1)
      protected 'name' => null
      protected 'serviceManager' => null
  protected 'otys' => null
  protected 'address' => string 'Langebrug 87 b' (length=14)
  protected 'postalcode' => string '2311 TJ' (length=7)
  protected 'city' => string 'Leiden' (length=6)
  protected 'email' => null
  protected 'country' => 
    object(DoctrineORMModule\Proxy\__CG__\ZF2Country\Entity\Country)[724]
      public '__initializer__' => 
        object(Closure)[711]
      public '__cloner__' => 
        object(Closure)[710]
      public '__isInitialized__' => boolean false
      protected 'countryId' => string '157' (length=3)
      protected 'nameIso' => null
      protected 'name' => null
      protected 'iso' => null
      protected 'iso3' => null
      protected 'serviceManager' => null
  protected 'created' => 
    object(DateTime)[698]
      public 'date' => string '2014-03-22 16:05:49' (length=19)
      public 'timezone_type' => int 3
      public 'timezone' => string 'Europe/Amsterdam' (length=16)
  protected 'deleted' => null
  protected 'serviceManager' => null
like image 862
Dirkos Avatar asked Nov 01 '22 02:11

Dirkos


1 Answers

Let me investigate, what is the reason. Sometimes it is convenient to use Zend\Form\Select element, not Doctrine element. But Zend element sometimes can not deal with doctrine Entities. The reason is in the following code of file Zend\Form\View\Helper\FormSelect.php at method renderOptions.

if (ArrayUtils::inArray($value, $selectedOptions)) {
    $selected = true;
}

This piece of code makes every option selected. But $selectedOptions is not entity id, it is Entity object. This object is transformed into array via magic method, so we have wrong $selectedOptions.

So I've decided to change form element type from 'Select' to DoctrineModule\Form\Element\ObjectSelect and inject entityManager.

'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
    'object_manager' => $entityManager,
    'target_class' => 'Telecom\Entity\Name',
)

I dont know, why sometimes it is not a problem. Probably I should take a look at Proxy object, generated by Doctrine. I will update the answer if I understand something.

like image 139
shukshin.ivan Avatar answered Nov 15 '22 05:11

shukshin.ivan