One-To-many associations and forms based entirely on annotations

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

One-To-many associations and forms based entirely on annotations

cbichis
Hi,

I am trying to create some more complex forms (involving One-to-Many
relations in my case).entirelly using annotations (no separated
fieldsets created).

Is this entirely possible using annotations or I still need to create
separated fieldsets aggregate manually ?

After submitting the form it seems to have a hydrator issue I cant find
a solution to fix. I used 2 very simple entities illustrating my problem.


=================================
=== ERROR ===
=================================

AN ERROR OCCURRED

An error occurred during execution; please try again later.

Additional information:

Zend\Stdlib\Exception\BadMethodCallException

File:
/home/demo/vendor/zendframework/zendframework/library/Zend/Stdlib/Hydrator/ArraySerializable.php:78
Message:
Zend\Stdlib\Hydrator\ArraySerializable::hydrate expects the provided
object to implement exchangeArray() or populate()
Stack trace:
#0
/home/demo/vendor/zendframework/zendframework/library/Zend/Form/Fieldset.php(597):
Zend\Stdlib\Hydrator\ArraySerializable->hydrate(Array, NULL)
#1
/home/demo/vendor/zendframework/zendframework/library/Zend/Form/Element/Collection.php(273):
Zend\Form\Fieldset->bindValues(Array)
#2
/home/demo/vendor/zendframework/zendframework/library/Zend/Form/Fieldset.php(585):
Zend\Form\Element\Collection->bindValues(Array)
#3
/home/demo/vendor/zendframework/zendframework/library/Zend/Form/Form.php(364):
Zend\Form\Fieldset->bindValues(Array)
#4
/home/demo/vendor/zendframework/zendframework/library/Zend/Form/Form.php(513):
Zend\Form\Form->bindValues()
#5
/home/demo/module/Imagis/src/Imagis/Controller/AnnotationController.php(....):
Zend\Form\Form->isValid()
#7
/home/demo/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php(83):
Test\Controller\AnnotationController->addAction()
#8 [internal function]:
Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent))
#9
/home/demo/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468):
call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#10
/home/demo/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(207):
Zend\EventManager\EventManager->triggerListeners('dispatch',
Object(Zend\Mvc\MvcEvent), Object(Closure))
#11
/home/demo/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php(117):
Zend\EventManager\EventManager->trigger('dispatch',
Object(Zend\Mvc\MvcEvent), Object(Closure))
#12
/home/demo/vendor/zendframework/zendframework/library/Zend/Mvc/DispatchListener.php(114):
Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request),
Object(Zend\Http\PhpEnvironment\Response))
#13 [internal function]:
Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent))
#14
/home/demo/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468):
call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#15
/home/demo/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(207):
Zend\EventManager\EventManager->triggerListeners('dispatch',
Object(Zend\Mvc\MvcEvent), Object(Closure))
#16
/home/demo/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php(313):
Zend\EventManager\EventManager->trigger('dispatch',
Object(Zend\Mvc\MvcEvent), Object(Closure))
#17 /home/demo/public_html/index.php(17): Zend\Mvc\Application->run()
#18 {main}

=================================
=== Brand entity ===
=================================

/**
  * @ORM\Entity
  * @ORM\Table(name="test_brands",
uniqueConstraints={@ORM\UniqueConstraint(name="name", columns={"name"})})
  */
class Brand {

     /**
      * @var int
      * @ORM\Id
      * @ORM\Column(type="integer", nullable=false,
options={"unsigned"=true})
      * @ORM\GeneratedValue(strategy="IDENTITY")
      * @Annotation\Exclude()
      *
      */
     protected $id;

     /**
      * @var string
      * @Annotation\Type("Zend\Form\Element\Text")
      * @Annotation\Options({"label":"Brand Name"})
      * @Annotation\Required(true)
      * @ORM\Column(type="string", length=32, unique=true, nullable=false)
      */
     protected $name;

     /**
      *
@Annotation\ComposedObject({"target_object":"\Test\Entity\Model",
"is_collection":"true", "options":{"count":2,
"should_create_template":"true", "allow_add":"true",
"allow_remove":"true"}})
      * @ORM\OneToMany(targetEntity="Test\Entity\Model",
       mappedBy="product", cascade={"persist"})
      */
     protected $models;

     public function __construct() {
         $this->models = 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;
     }

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

         return $this;
     }

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

     /**
      * Add models
      *
      * @param \Doctrine\Common\Collections\Collection  $models
      */
     public function addModels($models) {
         foreach ($models as $model) {
             $model->setBrand($this);
             $this->models->add($model);
         }
     }

     /**
      * Remove models
      *
      * @param \Doctrine\Common\Collections\Collection  $models
      */
     public function removeModels($models) {
         foreach ($models as $model) {
             $model->setBrand(null);
             $this->models->removeElement($model);
         }
     }

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

}

=================================
=== Model entity ===
=================================

/**
  * @ORM\Entity
  * @ORM\Table(name="test_models")
  * @Annotation\Name("Model")
  * @Annotation\Type("fieldset")
  */
class Model {

     /**
      * @var int
      * @ORM\Id
      * @ORM\Column(type="integer", nullable=false,
options={"unsigned"=true})
      * @ORM\GeneratedValue(strategy="IDENTITY")
      * @Annotation\Exclude()
      */
     protected $id;

     /**
      * @var string
      * @Annotation\Flags({"priority": 100})
      * @Annotation\AllowEmpty(true)
      * @Annotation\Type("Zend\Form\Element\Text")
      * @Annotation\Options({"label":"Model name"})
      * @ORM\Column(type="string", nullable=false)
      */
     protected $name;

     /**
      * @Annotation\Exclude()
      * @ORM\ManyToOne(targetEntity="Test\Entity\Brand",
inversedBy="models")
      * @ORM\JoinColumn(name="brand", referencedColumnName="id",
onDelete="CASCADE")
      */
     protected $brand;

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

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

         return $this;
     }

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

     public function setBrand(Brand $brand = null) {
         $this->brand = $brand;
     }

     public function getBrand() {
         return $this->brand;
     }
}


=================================
=== Controller ===
=================================

$entityClass = '\Test\Entity\Brand';

$id = $this->params()->fromRoute('id');
//update
if (!empty($id)) {
     $repository = $this->getObjectManager()->getRepository($entityClass);
     $this->entity = $repository->find($id);
} else {//create
     $this->entity = new $entityClass();
}

//form generation
$builder = new DoctrineAnnotationBuilder($this->getObjectManager());
$this->form = $builder->createForm($this->entity);
$this->form->setHydrator(new DoctrineHydrator($this->getObjectManager(),
$entityClass))
         ->setObject($this->entity);

$this->form->add(array(
     'type' => 'Zend\Form\Element\Csrf',
     'name' => 'security',
     'options' => array(
         'csrf_options' => array(
             'timeout' => 600
         )
     )
));

$this->form->add(array(
     'name' => 'submit',
     'type' => 'Submit',
     'attributes' => array(
         'value' => 'save',
     ),
));


//end form generation

$this->form->bind($this->entity);

$request = $this->getRequest();
if ($request->isPost()):
     $dataForm = array_replace_recursive(
             $request->getPost()->toArray(), $request->getFiles()->toArray()
     );

     $this->form->setData($dataForm);

     if ($this->form->isValid()):

$this->getObjectManager()->persist($this->entity);
         $this->getObjectManager()->flush();

     endif;
endif;


Thank you,
Cristian