Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 08-06-2018 17:17:22

zigo
Membre
Date d'inscription: 24-02-2016
Messages: 30

formCollections : Ajouter au moins deux éléments en plus

Hello smile

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 hmm 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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

Code:

[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

 

#2 13-06-2018 09:15:58

zigo
Membre
Date d'inscription: 24-02-2016
Messages: 30

Re: formCollections : Ajouter au moins deux éléments en plus

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

Code:

[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

Code:

[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

Code:

[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 smile

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages