Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Hello
Je continues un peu à faire vivre le forum en posant des questions !
J'ai trouvé ça http://www.z-f.fr/forum/viewtopic.php?id=9274 et j'ai le même problème sauf que perso je n'arrive pas à trouver la solution ^^. Malheureusement son sujet à 4 ans donc je m'en remet à vous.
J'ai essayé de suivre ce tuto de zend pour mon besoin : https://docs.zendframework.com/zend-for … ollections
J'ai un peu bloqué donc j'ai décidé de l'implémenter tel quel pour comprendre un peu mieux et j'en ressort avec ce soucis, je n'arrive à ajouter qu'un seul élément en plus. Le reste ne se trouve même pas dans mon $form->getData() Seul le dernier input dynamique est conservé.
La seule piste que j'ai c'est sa réponse : problème de setter dans l'entité.
Voici les fichiers : Je met tous ce qui fait beaucoup Et c'est dans la doc de zend fourni ci-dessus. Dans le var_dump, la catégorie Test3 n'est pas présente. Si j'en ajoute 3 en dynamique, ça sera Test5 dans l'objet sans Test3 et Test4.
Product.php
[lang=php] <?php namespace Product\Model; class Product { /** * @var string */ protected $name; /** * @var int */ protected $price; /** * @var Brand */ protected $brand; /** * @var array */ protected $categories; /** * @param string $name * @return self */ public function setName($name) { $this->name = $name; return $this; } /** * @return string */ public function getName() { return $this->name; } /** * @param int $price * @return self */ public function setPrice($price) { $this->price = $price; return $this; } /** * @return int */ public function getPrice() { return $this->price; } /** * @param Brand $brand * @return self */ public function setBrand(Brand $brand) { $this->brand = $brand; return $this; } /** * @return Brand */ public function getBrand() { return $this->brand; } /** * @param Category[] $categories * @return self */ public function setCategories(array $categories) { $this->categories = $categories; return $this; } /** * @return Category[] */ public function getCategories() { return $this->categories; } }
Brand.php
[lang=php] <?php namespace Product\Model; class Brand { /** * @var string */ protected $name; /** * @var string */ protected $url; /** * @param string $name * @return self */ public function setName($name) { $this->name = $name; return $this; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $url * @return self */ public function setUrl($url) { $this->url = $url; return $this; } /** * @return string */ public function getUrl() { return $this->url; } }
Category.php
[lang=php] <?php namespace Product\Model; /** * Created by PhpStorm. * User: nzilberm * Date: 07/06/2018 * Time: 17:29 */ class Category { /** * @var string */ protected $name; /** * @param string $name * @return self */ public function setName($name) { $this->name = $name; return $this; } /** * @return string */ public function getName() { return $this->name; } }
ProductFieldset.php
[lang=php] <?php namespace Product\Form; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; use Zend\Stdlib\Hydrator\ClassMethods as ClassMethods; use Product\Model\Product; use Zend\Form\Element; class ProductFieldset extends Fieldset implements InputFilterProviderInterface { public function __construct() { parent::__construct('product'); $this->setHydrator(new ClassMethods(false)); $this->setObject(new Product()); $this->add([ 'name' => 'name', 'options' => [ 'label' => 'Name of the product', ], 'attributes' => [ 'required' => 'required', ], ]); $this->add([ 'name' => 'price', 'options' => [ 'label' => 'Price of the product', ], 'attributes' => [ 'required' => 'required', ], ]); $this->add([ 'type' => BrandFieldset::class, 'name' => 'brand', 'options' => [ 'label' => 'Brand of the product', ], ]); $this->add([ 'type' => Element\Collection::class, 'name' => 'categories', 'options' => [ 'label' => 'Please choose a category', 'count' => 2, 'should_create_template' => true, 'allow_add' => true, 'template_placeholder' => '__placeholder__', 'target_element' => [ 'type' => CategoryFieldset::class, ], ], ]); } /** * Should return an array specification compatible with * {@link Zend\InputFilter\Factory::createInputFilter()}. * * @return array */ public function getInputFilterSpecification() { return [ 'name' => [ 'required' => true, ], 'price' => [ 'required' => true, 'validators' => [ [ 'name' => 'Float', ], ], ], ]; } }
BrandFieldset.php
[lang=php] <?php namespace Product\Form; use Product\Model\Brand; use Zend\Form\Element; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; use Zend\Stdlib\Hydrator\ClassMethods as ClassMethods; class BrandFieldset extends Fieldset implements InputFilterProviderInterface { public function __construct() { parent::__construct('brand'); $this->setHydrator(new ClassMethods(false)); $this->setObject(new Brand()); $this->add([ 'name' => 'name', 'options' => [ 'label' => 'Name of the brand', ], 'attributes' => [ 'required' => 'required', ], ]); $this->add([ 'name' => 'url', 'type' => Element\Url::class, 'options' => [ 'label' => 'Website of the brand', ], 'attributes' => [ 'required' => 'required', ], ]); } /** * @return array */ public function getInputFilterSpecification() { return [ 'name' => [ 'required' => true, ], ]; } }
CategoryFieldset.php
[lang=php] <?php namespace Product\Form; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; use Zend\Stdlib\Hydrator\ClassMethods as ClassMethods; use Product\Model\Category; class CategoryFieldset extends Fieldset implements InputFilterProviderInterface { public function __construct() { parent::__construct('category'); $this->setHydrator(new ClassMethods(false)); $this->setObject(new Category()); $this->setLabel('Category'); $this->add([ 'name' => 'name', 'options' => [ 'label' => 'Name of the category', ], 'attributes' => [ 'required' => 'required', ], ]); } /** * @return array */ public function getInputFilterSpecification() { return [ 'name' => [ 'required' => true, ], ]; } }
CreateProductForm.php
[lang=php] <?php namespace Product\Form; use Zend\Form\Form; use Zend\InputFilter\InputFilter; use Zend\Stdlib\Hydrator\ClassMethods as ClassMethods; use Zend\Form\Element; class CreateProductForm extends Form { public function __construct() { parent::__construct('create_product'); $this->setAttribute('method', 'post'); $this->setHydrator(new ClassMethods(false)); $this->setInputFilter(new InputFilter()); $this->add([ 'type' => ProductFieldset::class, 'options' => [ 'use_as_base_fieldset' => true, ], ]); $this->add([ 'type' => Element\Csrf::class, 'name' => 'csrf', ]); $this->add([ 'name' => 'submit', 'attributes' => [ 'type' => 'submit', 'value' => 'Send', ], ]); } }
ProductController.php
[lang=php] public function indexAction() { $form = new CreateProductForm(); $product = new Product(); $form->bind($product); $request = $this->getRequest(); if ($request->isPost()) { $form->setData($request->getPost()); if ($form->isValid()) { var_dump($product); exit; } } return [ 'form' => $form, ]; }
index.phtml
[lang=php] <?php $this->form->setAttribute('action', $this->url('administration/product')); $this->form->prepare(); echo $this->form()->openTag($this->form); $product = $this->form->get('product'); // The name and price can be rendered as regular elements: echo $this->formRow($product->get('name')); echo $this->formRow($product->get('price')); // Categories are rendered as a collection: ?> <div class="categories"> <?php echo $this->formCollection($product->get('categories'));?> <button class="add_input">Add a new category</button> </div> <?php $brand = $product->get('brand'); // Since the brand is a 1:1 relationship, its elements are rendered normally: echo $this->formRow($brand->get('name')); echo $this->formRow($brand->get('url')); // And finally, we render the CSRF and submit elements: echo $this->formHidden($this->form->get('csrf')); echo $this->formElement($this->form->get('submit')); echo $this->form()->closeTag(); $this->inlineScript() ->prependFile($this->basePath('dist/js/admin.min.js')) ->appendFile($this->basePath('assets/src/js/timetable.js'));
Le résultat de mon var_dump
[lang=php] object(Product\Model\Product)[679] protected 'name' => string 'Test' (length=4) protected 'price' => string '1234' (length=4) protected 'brand' => object(Product\Model\Brand)[653] protected 'name' => string 'Test' (length=4) protected 'url' => string 'http://test.com' (length=15) protected 'categories' => array (size=3) 0 => object(Product\Model\Category)[684] protected 'name' => string 'Test' (length=4) 1 => object(Product\Model\Category)[688] protected 'name' => string 'Test2' (length=5) 2 => object(Product\Model\Category)[692] protected 'name' => string 'Test4' (length=5)
Manque que le JS mais mon bouton d'ajout fonctionne donc je me dis que le problème devrait pas être là.
Merci à vous !!
Hors ligne
Bonjour,
J'ai repris l'implémentation d'une formCollection directement sur mon projet et ça passe (comme la personne avant)
Par contre je ne comprends pas pourquoi ça fonctionne et ça ça me dérange !
Voici mon implémentation : En plus rapide que la première :p
Mon Fieldset
[lang=php] <?php namespace Site\Form; use Site\Model\TimeDay; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; use Zend\Stdlib\Hydrator\ClassMethods; class TimeDayFieldset extends Fieldset implements InputFilterProviderInterface { public function __construct() { parent::__construct('timeday'); $this ->setHydrator(new ClassMethods(false)) ->setObject(new TimeDay()); $this->add( [ 'name' => 'from', 'type' => 'text', 'options' => [ 'label' => 'From', ], 'attributes' => [ 'required' => 'required', 'class' => 'timepicker col-md-6' ] ] ); $this->add( [ 'name' => 'to', 'type' => 'text', 'options' => [ 'label' => 'To', ], 'attributes' => [ 'required' => 'required', 'class' => 'timepicker col-md-6' ] ] ); } /** * @return array */ public function getInputFilterSpecification() { return array( 'from' => [ 'required' => true, ], 'to' => [ 'required' => true ] ); } }
Mon Objet
[lang=php] <?php namespace Site\Model; class TimeDay { /** * @var string */ protected $from; /** * @var string */ protected $to; /** * @return string */ public function getFrom() { return $this->from; } /** * @param string $from */ public function setFrom($from) { $this->from = $from; } /** * @return string */ public function getTo() { return $this->to; } /** * @param string $to */ public function setTo($to) { $this->to = $to; } }
Et le rajout dans mon form
[lang=php] $days = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]; for($i=0;$i<count($days);$i++){ $this->add( [ 'type' => 'collection', 'name' => $days[$i], 'options' => [ //'label' => 'Monday', 'count' => 0, 'should_create_template' => true, 'allow_add' => true, 'allow_remove' => true, //'template_placeholder' => '__placeholder__', 'target_element' => [ 'type' => TimeDayFieldset::class, ], ], ] ); }
Et là je peux bien récupérer tout les objets créés dynamiquement après le post dans mon controller.
Une idée de pourquoi ça fonctionnerait dans le premier cas et pas dans le deuxième ?
Merci
Hors ligne