Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 18-03-2014 20:23:03

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Problème avec la validation d'un formulaire

Bonsoir à tous,

j'ai un problème lorsque je valide mon formulaire, j'obtiens le message suivant dont je n'ai pas trouvé la solution sur Google :

Notice: Array to string conversion in C:\Users\Romain\Documents\GitHub\royalepizza\vendor\ZF2\library\Zend\Validator\AbstractValidator.php on line 159

et ce message apparait 8 fois.

J'ai un formulaire "CommandeForm.php" :

Code:

[lang=php]<?php
namespace Front\Form;

use Custom\Form\AbstractForm;

use Zend\Form\Element;
use Zend\Form\Form;

class CommandeForm extends AbstractForm
{
    public function initialize()
    {        
        // On définit la méthode d'envoie du formulaire en POST
        $this->setAttribute('method', 'post');
        
        $this->add(array(
            'type' => 'Zend\Form\Element\Select',
            'name' => 'taille',
            'attributes' => array(
                'required' => true,
                'class' => 'taille',
            ),
        ));
        
        $this->add(array(
            'type' => 'Zend\Form\Element\Select',
            'name' => 'sauce',
            'attributes' => array(
                'required' => true,
                'class' => 'sauce',
            ),
        ));
        
        $this->add(array(
                'type' => 'Zend\Form\Element\MultiCheckbox',
                'name' => 'ingredients',
                 'attributes' => array(
                      'required' => true,
                     'class' => 'ingredients',
                  ),
        ));
        
        $this->add(array(
                'type' => 'Zend\Form\Element\MultiCheckbox',
                'name' => 'boissons',
                'required' => false,
                'attributes' => array(
                    'class' => 'boissons',
                ),
        ));
        
        $this->add(array(
                'type' => 'Zend\Form\Element\MultiCheckbox',
                'name' => 'desserts',
                'required' => false,
                'attributes' => array(
                        'class' => 'desserts',
                ),
        ));
        
        $this->add(array(
            'name' => 'nom',
            'attributes' => array(
                'type'  => 'text',
                'required' => true,
                'placeholder' => 'Le nom de votre pizza',
                'class' => 'nom',
            ),
        ));

        $this->add(
            array(
                'name' => 'csrf',
                'type' => 'Csrf',
                'options' => array(
                    'csrf_options' => array(
                        'timeout' => 600
                    )
                )
             )
        );
        
        $this->add(array(
            'name' => 'submit',        // Nom du champ
            'type' => 'Submit',        // Type du champ
            'attributes' => array(     // On va définir quelques attributs
                'value' => 'Ajouter',  // comme la valeur
                'id' => 'submit',      // et l'id
            ),
        ));
    }
}

Un modèle "Commande.php" pour les inputsFilters et Validateurs :

Code:

[lang=php]<?php
namespace Front\Model;

use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilter;

class Commande implements InputFilterAwareInterface
{
    protected $inputFilter;
    
    // La méthode setInputFilter ne sera pas utilisé ici...
    public function setInputFilter(\Zend\InputFilter\InputFilterInterface $inputFilter)
    {
        $this->inputFilter = $inputFilter;
    }

    // La méthode qui nous intéresse
    public function getInputFilter()
    {
        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();

            $inputFilter->add(
                array(
                    'name'     => 'nom',               // Le nom du champ / de la propriété
                    'required' => true,                 // Champ requis
                    'filters'  => array(                // Différents filtres:
                        array('name' => 'StripTags'),   // Pour retirer les tags HTML
                        array('name' => 'StringTrim'),  // Pour supprimer les espaces avant et apres le nom
                    ),
                    'validators' => array(              // Des validateurs
                        array(
                            'name'    => 'StringLength',// Pour vérifier la longueur du nom
                            'options' => array(
                                'encoding' => 'UTF-8',  // La chaine devra être en UTF-8
                                'min'      => 1,        // et une longueur entre 1 et 100
                                'max'      => 100,
                            ),
                        ),
                    ),
                )
            );

            $this->inputFilter = $inputFilter;
        }

        return $this->inputFilter;
    }
}

et une action "ajouterPanierAction()" dans mon IndexController afin de gérer le retour du formulaire :

Code:

[lang=php]    public function ajouterPanierAction()
    {
        $formCommande = $this->_getFrontFormCommande();
        
        // On récupère l'objet Request
        $request = $this->getRequest();
        
        if ($request->isPost()) {
            // On instancie notre modèle Commande
            $commande = new Commande();

            // Et on passe l'InputFilter de Commande au formulaire
            $formCommande->setInputFilter($commande->getInputFilter());
            $formCommande->setData($request->getPost());

                // print_r($_POST);

            if (isset($_POST['submit']) && $formCommande->isValid()) {
                
                $data = $formCommande->getData();
            }
        }
    }

Lorsque je décommente le "print_r($_POST);" ci-dessus j'obtiens bien mes données :

Code:

Array ( [csrf] => fcda50bf182eda8790d1ef1fba52bcee [taille] => Grande/8 [sauce] => Sauce blanche/1 [ingredients] => Array ( [0] => viande de kébab/0.60 [1] => oignons/0.10 [2] => olives/0.10 ) [nom] => kebab [boissons] => Array ( [0] => coca cola/1.50 ) [desserts] => Array ( [0] => moelleux au chocolat/2 ) [submit] => Ajouter )

Le problème vient du "$formCommande->isValid()", mais pourquoi?

Merci

Dernière modification par romsVLM (18-03-2014 20:25:00)

Hors ligne

 

#2 19-03-2014 08:57:29

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

Hello,
Je ne suis pas sur (je n'ai pas mon environnement de dev pour vérifier) mais tu devrais commencer par mettre un inputFilter pour chacune des données de ton objet smile
Même si ça ne viens pas de la, tu ne doit pas faire confiance à l'utilisateur et toujours vérifier ce qu'il te transmet.

Hors ligne

 

#3 19-03-2014 10:39:51

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Oui oui j'avais essayé aussi, meme en mettant 7 ou 8 inputFilters, j'obtiens toujours les 8 messages.

Hors ligne

 

#4 19-03-2014 10:48:42

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

Salut, sur les formulaire je te conseil de suivre les différents retour qui ont été donné sur ce forum. Je vais tout de même te faire un petit rappel ça pourrait t'aider je pense wink.

Concernant ton problème ça vient du fais que tu n'utilises pas la bonne interface wink. C'est InputFilterProviderInterface et non InputFilterAwareInterface

Dans un premier temps il faut garder à l'esprit qu'un formulaire correctement configuré est composé d'un ou plusieurs fieldset (dont un principal), d'un csrf, d'un bouton submit voir éventuellement un bouton reset et d'input n'ayant pas de rapports direct avec un modèle/entité. Ensuite il peut aussi contenir des éléments spécifiques mais je vais y revenir un peu plus bas notamment un validationGroup.

Concernant le csrf, les boutons submit et reset je pense qu'il est inutile que je revienne dessus c'est assez simple. Le plus important c'est le fieldset car il faut bien comprendre son intérêt. Un fieldset est un morceau de formulaire qui est chargé de représenté une entité de cette façon on décharge l'entité de sa propre validation (comme tu l'as fait) et on déporte ça dans une classe qui est faite pour ça.
On va prendre l'exemple d'une entité utilisateur et de deux actions : inscription et mise à jour de l'utilisateur (partie admin).
Pour se faire tu vas d'abord devoir créer une fieldset de ton entité utilisateur qui va représenter tous les attributs de la classe (ils ne serviront pas forcément tous) de façon à avoir une représentation de celle-ci sous forme de formulaire. Pour chaque type d'attribut tu as un input associé (string => type text, relation ManyToOne => type select/radio, ManyToMany => type checkbox etc ...).
Ce fieldset va se charger aussi de la validation tu vas donc devoir implémenter l'interface InputFilterProviderInterface et définir tes inputFilter.

Une fois ça fait logiquement tu as ton entité et un fieldset qui la représente et la valide qui doit ressembler à quelque chose comme ça (profites c'est pas souvent que je donne du code wink).

Code:

[lang=php]
<?php

namespace User\Form\Fieldset;

use DoctrineModule\Persistence\ProvidesObjectManager;
use User\Entity\Membre;
use Zend\InputFilter\InputFilterProviderInterface;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Zend\Form\Fieldset;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;

class UserFieldset extends Fieldset implements
    ObjectManagerAwareInterface,
    InputFilterProviderInterface
{
    use ProvidesObjectManager;

    public function init()
    {
        $this->setHydrator(new DoctrineHydrator($this->getObjectManager(), 'User\Entity\Membre'))
            ->setObject(new Membre());

        // Id nécessaire pour certaines validations
        $this->add(
            array(
                'type' => 'Zend\Form\Element\Hidden',
                'name' => 'id'
            )
        );

        // Login
        $this->add(
            array(
                'name' => 'login',
                'type' => 'Zend\Form\Element\Text',
                'attributes' => array(
                    'class' => 'form-control',
                    'required' => 'required',
                    'id' => 'login',
                ),
                'options' => array(
                    'label' => 'Pseudo',
                ),
            )
        );

        // Email
        $this->add(
            array(
                'name' => 'email',
                'type' => 'Zend\Form\Element\Email',
                'attributes' => array(
                    'class' => 'form-control',
                    'required' => 'required',
                    'id' => 'email'
                ),
                'options' => array(
                    'label' => 'Email'
                ),
            )
        );

        // Password
        $this->add(
            array(
                'name' => 'password',
                'type' => 'Zend\Form\Element\Password',
                'attributes' => array(
                    'class' => 'form-control',
                    'required' => 'required',
                    'id' => 'password',
                ),
                'options' => array(
                    'label' => 'Mot de passe',
                ),
            )
        );
    }

    /**
     *
     * @return array
     */
    public function getInputFilterSpecification()
    {
        return array(
            'login' => array(
                'required' => false,
                'filters' => array(
                    array(
                        'name' => 'StringTrim'
                    )
                ),
                'validators' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'min' => 2,
                            'max' => 40,
                        ),
                    ),
                ),
            ),
            'email' => array(
                'required' => true,
                'filters' => array(
                    array(
                        'name' => 'StringTrim'
                    )
                ),
                'validators' => array(
                    array(
                        'name' => 'EmailAddress', // A vérifier si l'alias est bien celui-ci
                    ),
                ),
            ),
            'password' => array(
                'required' => true,
            ),
        );
    }
}

Maintenant il faut gérer les deux cas : inscription et mise à jour (partie admin). Pour ça tu dois créer 2 formulaires. Une formulaire est chargé de remplir qu'une seule action (tu verras pourquoi plus tard). Forcément il y a un peu de duplication de code mais au final c'est assez peu grâce au fieldset et beaucoup plus simple à l'utilisation.
Dans le cas de l'inscription tu vas vérifier par exemple que le login et l'adresse mail ne sont pas déjà utilisée dans la base, tu vas vouloir confirmer le mot de passe et l'adresse mail. Tout ça ce n'est pas lié à ton entité et donc ton fieldset mais bien à l'action inscription du formulaire donc tu feras les vérifications dans ton formulaire. Admettons que tu as une gestion de rôles, lors de l'inscription tu vas pas permettre à l'utilisateur de choisir son rôle tu vas le faire toi même en interne, pourtant tu vas avoir un élément de formulaire qui va se charger de le faire sauf qu'il est inutile dans le cas de l'inscription. Pour ça tu vas utiliser un validationGroup pour indiquer quels champs tu veux valider. De cette façon ton formulaire n'aura accès qu'aux éléments présent dans la validationGroup, comme ça pas de prise de tête ni de confusion. Ton formulaire d'inscription va ressemble à ça :

Code:

[lang=php]
<?php

namespace User\Form;

use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use DoctrineModule\Persistence\ProvidesObjectManager;
use DoctrineModule\Validator\NoObjectExists;
use Zend\Form\Form;
use Zend\Validator\Identical;
use Zend\Validator\ValidatorChain;

class RegisterForm extends Form implements ObjectManagerAwareInterface
{
    use ProvidesObjectManager;

    public function init()
    {
        $this->add(
            array(
                'name' => 'user',
                'type' => 'User\Form\Fieldset\UserFieldset',
                'options' => array(
                    'use_as_base_fieldset' => true,
                ),
            )
        );

        $this->setValidationGroup(
            array(
                'user' => array(
                    'login',
                    'email',
                    'password',
                ),
                'confirmEmail',
                'confirmPassword',
            )
        );

        $this->add(
            array(
                'name' => 'confirmPassword',
                'type' => 'Zend\Form\Element\Password',
                'attributes' => array(
                    'class' => 'form-control',
                    'required' => 'required',
                    'id' => 'confirmPassword',
                ),
                'options' => array(
                    'label' => 'Confirmer mot de passe',
                ),
            )
        );

        $this->add(
            array(
                'name' => 'confirmEmail',
                'type' => 'Zend\Form\Element\Email',
                'attributes' => array(
                    'class' => 'form-control',
                    'required' => 'required',
                    'id' => 'confirmEmail',
                ),
                'options' => array(
                    'label' => 'Confirmer email',
                ),
            )
        );

        // Add the unique validator so that emails are unique
        $inputPassword = $this->getInputFilter()->get('confirmPassword');
        /** @var ValidatorChain $validators */
        $validators = $inputPassword->getValidatorChain();

        $validators->attach(
            new Identical(array('user' => 'password'))
        );

        // Add the unique validator so that emails are unique
        $inputEmail = $this->getInputFilter()->get('confirmEmail');
        /** @var ValidatorChain $validators */
        $validators = $inputEmail->getValidatorChain();

        $validators->attach(
            new Identical(array('user' => 'email'))
        );

        $userInput = $this->getInputFilter()->get('user');
        $mailInput = $userInput->get('email');
        $validators = $mailInput->getValidatorChain();

        $validators->attach(
            new NoObjectExists(array(
                'object_repository' => $this->getObjectManager()->getRepository('User\Entity\Membre'),
                'fields' => 'email',
                'messages' => array(
                    NoObjectExists::ERROR_OBJECT_FOUND => "Il existe déjà un utilisateur avec cette adresse email",
                )
            ))
        );

        $loginInput = $userInput->get('login');
        $validators = $loginInput->getValidatorChain();

        $validators->attach(
            new NoObjectExists(array(
                'object_repository' => $this->getObjectManager()->getRepository('User\Entity\Membre'),
                'fields' => 'login',
                'messages' => array(
                    NoObjectExists::ERROR_OBJECT_FOUND => "Il existe déjà un utilisateur avec ce pseudo",
                )
            ))
        );

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

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

Tu peux constater que j'ai rajouté des éléments qui n'ont aucun rapport avec l'entité mais bien avec l'action en cours. Tu vas pas stocker en base la confirmation de mot de passe ou celle de l'email.

Maintenant que le cas de l'inscription est traité tu as besoin de faire celui de la mise à jour côté administration (puisqu'on va rajouter le rôle). Le rôle n'est pas présent dans le fieldset donc à toi de le rajouter en fonction de ce que tu as besoin ce ne sont que des exemples pour t'inspirer wink. Dans la mise à jour de l'utilisateur on ne permet pas la modification du mot de passe mais celle de l'email. Tu noteras que j'ai oublié de confirmer l'email mais comme c'est partie administrateur c'est moins gênant wink. De plus on ne va pas vérifier si l'email existe déjà puisque dans le cas où on le modifie pas la validation sera fausse l'email existera puisqu'il sera toujours attaché à l'utilisateur que l'on modifie. Même chose pour le login. Pour ça on vérifie s'il est unique en base de cette façon on garde l'intégrité des données, on peut le modifier comme on veut s'ils sont déjà utilisé ça sera invalidé etc ... Dans le cas d'une validation via le validateur Unique il faut indiquer un champ id dans le fieldset de type hidden (c'est mieux) pour gêrer le unique sans bloquer la validation de l'utilisateur que l'on modifie.

Code:

[lang=php]
<?php

namespace User\Form;

use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use DoctrineModule\Persistence\ProvidesObjectManager;
use DoctrineModule\Validator\UniqueObject;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\ProvidesEvents;
use Zend\Form\Form;

class UpdateUserForm extends Form implements
    EventManagerAwareInterface,
    ObjectManagerAwareInterface
{
    use ProvidesEvents;
    use ProvidesObjectManager;

    public function init()
    {

        $this->add(
            array(
                'name' => 'user',
                'type' => 'User\Form\Fieldset\UserFieldset',
                'options' => array(
                    'use_as_base_fieldset' => true,
                ),
            )
        );

        $this->setValidationGroup(
            array(
                'user' => array(
                    'id',
                    'login',
                    'email',
                    'role',
                )
            )
        );

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

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

        // Add the unique validator so that emails are unique
        $userInput = $this->getInputFilter()->get('user');
        $mailInput = $userInput->get('email');
        $validators = $mailInput->getValidatorChain();

        $validators->attach(
            new UniqueObject(array(
                'object_repository' => $this->getObjectManager()->getRepository('User\Entity\Membre'),
                'object_manager' => $this->getObjectManager(),
                'fields' => 'email',
                'messages' => array(
                    UniqueObject::ERROR_OBJECT_NOT_UNIQUE => "Il existe déjà un utilisateur avec cette adresse email"
                )
            ))
        );

        $loginInput = $userInput->get('login');
        $validators = $loginInput->getValidatorChain();

        $validators->attach(
            new UniqueObject(array(
                'object_repository' => $this->getObjectManager()->getRepository('User\Entity\Membre'),
                'object_manager' => $this->getObjectManager(),
                'fields' => 'login',
                'messages' => array(
                    UniqueObject::ERROR_OBJECT_NOT_UNIQUE => "Il existe déjà un utilisateur avec ce pseudo"
                )
            ))
        );
    }
}

Tu noteras aussi que j'utilise Doctrine donc il y aura sûrement des changements à faire si tu ne l'utilises pas.

Voila grosso modo comment il faut faire, on peut encore l'améliorer mais en faisant comme ça tu n'auras pas de problèmes de validation et tu sépares bien les différentes étapes de ton formulaire smile.
Je t'encourage aussi vivement à éviter de copier/coller ce code bêtement (ce pourquoi j'en donne rarement car ça débloque mais si on ne comprend pas ça sert à rien) et plutôt à poser des questions si tu as des interrogations wink !

Hors ligne

 

#5 19-03-2014 10:54:37

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

Voila c'est ce que je voulais te dire mais Orkin la fait avant moi.
hum...

Non mais ce pavet xD

Hors ligne

 

#6 19-03-2014 10:57:57

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

Comme ça c'est fait, si quelqu'un d'autre pose la question c'est qu'il a pas cherché wink !

Hors ligne

 

#7 19-03-2014 11:01:04

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

Je pense qu'on va plus voir romsVLM avant un moment, le temps qu'il déchiffre tout ça... =d

Mais bon, c'est plutôt complet, on devrait plus avoir de question sur la validation de formulaire ^^

Hors ligne

 

#8 19-03-2014 13:22:41

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Merci pour votre aide. il est vrai que c'est pas facile de trouver une bonne façon de procéder, je devrais plus souvent suivre la doc, plutôt que les tutos sur le net.

Pour revenir à mon problème, si j'ai bien compris, voila en gros ce que je dois faire :

1) Créer une entité Commande.php : Cette entité réfère les lignes de ma table Commande dans ma BDD.

2) Une classe CommandeFieldset : Création de mon fieldset contenant les champs qui ont une correspondance avec mon entité ( dans mon cas tout les champs sauf csrf, captchat, et le submit) + les filters + validators

3) Une classe AjouterCommandeForm : Appel du fieldset + création des champs csrf + captcha + submit

4) Une action IndexAction dans mon IndexController : Création + envoi à la vue de mon formulaire

5) Une action ajouterCommandeAction dans mon IndexController : Traitement du retour du formulaire (insertion dans la table Commande) + redirection


J'ai bien saisi le principe ?

Hors ligne

 

#9 19-03-2014 14:04:48

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

Oui tu as tout compris. Concernant l'action dans le contrôleur tu n'est pas obligé d'en avoir 2 différentes tu peux très bien afficher le formulaire sur ajouterCommandeAction et traiter le formulaire uniquement lorsque tu es en post donc $this->getRequest()->isPost();

Hors ligne

 

#10 19-03-2014 14:08:17

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Ok merci, j'implémente, je reviens vers vous en cas de soucis smile

Hors ligne

 

#11 19-03-2014 16:19:07

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Bon j'ai implémenté, tout semble correct.

J'ai quand même une erreur dans mon controlleur lorsque je veux sauvegarder mes données du formulaire en base une fois celles ci passé le validator.

indexAction() de mon IndexController :

Code:

[lang=php]
    public function indexAction()
    {
        $formCommande = new AjouterCommandeForm();
        $request = $this->getRequest();
        $commande = new Commande();
        $formCommande->bind($commande);
        
        // récupère toutes les tailles de pizza
        $tabOptionTaille = $this->taillePizzaTable->getAllOrder('id_taille');
        
        // récupère toutes les sauces de pizza
        $tabOptionSauce = $this->alimentTable->getAllAlimentsByName('Sauce');
        
        // récupère tous les ingrédients de pizza
        $tabOptionIngredient = $this->alimentTable->getAllAlimentsByName('Ingredient');

        // récupère toutes les boissons
        $tabOptionBoisson = $this->alimentTable->getAllAlimentsByName('Boisson');
                
        // récupère tous les desserts
        $tabOptionDessert = $this->alimentTable->getAllAlimentsByName('Dessert');
                        
        // ajoute les données dans les champs du select et du multicheckbox
        $formCommande->get('commande')->get('taille')->setValueOptions($tabOptionTaille);
        $formCommande->get('commande')->get('sauce')->setValueOptions($tabOptionSauce);
        $formCommande->get('commande')->get('ingredients')->setValueOptions($tabOptionIngredient);
        $formCommande->get('commande')->get('boissons')->setValueOptions($tabOptionBoisson);        
        $formCommande->get('commande')->get('desserts')->setValueOptions($tabOptionDessert);
        
        if ($this->request->isPost()) {
            $formCommande->setData($request->getPost());
        
            if ($formCommande->isValid()) {
                //$commande->exchangeArray($formCommande->getData());
                $this->commandeTable->saveCommande($formCommande->getData());
            }
        }
        
        return new ViewModel(
                array(
                    'form' => $formCommande,
                )
        );
    }

j'obtiens l'erreue suivante :
Fatal error: Call to a member function saveCommande() on a non-object in C:\Users\Romain\Documents\GitHub\royalepizza\module\Front\src\Front\Controller\IndexController.php on line 58

Voici ma méthode de sauvegarde :

Code:

[lang=php]
    public function saveCommande(Commande $commande)
    {
        $data = array(
            'id_commande' => $commande->id_commande,
            'nom_pizza'  => $commande->nom_pizza,
            'sauce_pizza' => $commande->sauce,
            'taille_pizza' => $commande->taille,
            'ingredients' => $commande->ingredients,
            'desserts' => $commande->dessets,
            'boissons' => $commande->boissons,
            'total' => $commande->total,
        );

        $id = (int)$commande->id_commande;

        if ($id == 0) {
            $this->tableGateway->insert($data);
        } elseif ($this->getCommande($id)) {
            $this->tableGateway->update(
                $data,
                array(
                    'id_commande' => $id,
                )
            );
        } else {
            throw new \Exception('Form id does not exist');
        }
    }

Une idée ?

Hors ligne

 

#12 19-03-2014 16:46:35

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

Code:

[lang=php]
 $this->commandeTable->saveCommande($formCommande->getData());

tu a besoin de passer par ton objet commande pour effectué ta fonction. (j'imagine qu'elle est dans ta classe Commande mmhh? ^^)

donc ça devrait être plus quelque chose du genre :

Code:

[lang=php]
 $commande->saveCommande($formCommande->getData());

EDIT: my bad, j'ai mal lu ta fonction.
mais tu devrais la placer la où j'ai indiqué juste avant ^^

Dans ton cas, tu à du placer ta fonction dans une classe qu'il faut que tu instancie, je ne sais pas si tu a fais quelque chose comme


Code:

[lang=php]
class CommandeTable
{
...
}

mais Il te manque l'objet pour appeler la fonction ^^

Dernière modification par flobrflo (19-03-2014 17:01:25)

Hors ligne

 

#13 19-03-2014 16:56:07

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Oui j'ai une classe CommandeTable pour les accès à la table commande.

Pourtant cette classe est bien appelée, la liaison à bien lieu. La liaison se fait dans mon Module, pour appelé un modèle d'accès à ma BDD j'ai juste besoin de faire $this->commandeTable->nom_méthode().

De plus tu peux voir ci dessus cette ligne qui fonctionne également :     
$tabOptionBoisson = $this->alimentTable->getAllAlimentsByName('Boisson');

Je pense que le problème vient du faite que ma méthode save attend un objet, et que je lui passe un array

Hors ligne

 

#14 19-03-2014 17:01:49

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

Pour créer ton formulaire passes par un formElementManager ça t'éviteras d'avoir des surprises wink. Là ça ne plante par parce que tu n'as pas d'interface de type AwareInterface d'implémenté dans ton formulaire mais ça arrivera peut être wink.

Honnêtement relis-toi, ces erreurs c'est des erreurs PHP qui n'ont rien à voir avec le ZF2. Là tu appelles une fonction sur l'objet qui est stocké dans $this->commandeTable hors il te dit que ce n'est pas un objet. Donc que $this->commandeTable n'est jamais instancié donc la fonction n'est pas accessible. C'est un peu comme si je faisais ça :

Code:

[lang=php]
$toto = null;
$toto->maFonctionDeLaMortQuiTue();

ça plante forcément ... Donc avant tu dois faire :

Code:

[lang=php]
$toto = new Toto();
$toto->maFonctionDeLaMortQuiTue(); // Faut que cette fonction existe dans la classe Toto

Donc relis bien ton code parce que c'est des erreurs bêtes avec des messages d'erreurs clairs. Autant avant c'était un problème d'utilisation du ZF2 avec un message pas forcément facile à comprendre. Là il te dit simplement que l'objet n'existe pas donc il ne peut pas connaitre la fonction.

Autre chose la partie de récupération et sauvegarde des données se fait dans une couche service et non dans le contrôleur. Tu devrais donc avoir une classe de service qui s'occupe de faire ça wink.

romsVLM a écrit:

De plus tu peux voir ci dessus cette ligne qui fonctionne également :     
$tabOptionBoisson = $this->alimentTable->getAllAlimentsByName('Boisson');

Clairement le message indique que $this->commandeTable n'est pas défini donc l'erreur vient de là. Fais un var_dump($this->commandeTable); ça devrait retourner null.

romsVLM a écrit:

Je pense que le problème vient du faite que ma méthode save attend un objet, et que je lui passe un array

Non car $form->getData() te retourne une instance de ton objet

Hors ligne

 

#15 19-03-2014 17:05:02

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

mmhh... j'utilise pas le ->bind(object)
alors la je vais avoir du mal à t'aider ^^

Essai de remplir ton objet commande et de le passer directement en paramètre plutôt que de passer par ton $formCommande

Code:

[lang=php]
//getById au pif!
$commande->getById(1);
//setRef au pif!
$commande->setRef('xxxxx');

$this->commandeTable->saveCommande($commande);

EDIT : Bon bah oublis xD
Merci Orkin tu me rassure me disait...$this->commandeTable ... j'ai manqué quelque chose... xD

Dernière modification par flobrflo (19-03-2014 17:06:49)

Hors ligne

 

#16 19-03-2014 17:13:42

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

flobrflo a écrit:

mmhh... j'utilise pas le ->bind(object)
alors la je vais avoir du mal à t'aider ^^

Ca te permet de lier un objet à ton formulaire. Comme ça lorsque tu fais un $form->getData() au lieu de te renvoyer un array il te renvoi un objet rempli à partir du moment où un hydrateur a été correctement défini dans le fieldset.

Hors ligne

 

#17 19-03-2014 17:15:52

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

mmmhhh... Je vais peut être m'y mettre alors ^^
ça m'évitera quelques lignes à chaque fois xD

Hors ligne

 

#18 19-03-2014 18:09:17

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Effectivement, erreur de ma part, j'avais une minuscule au lieu d'une majuscule.

Cette fois ma méthode save est bien appelée, cependant mes données sont vides.

Lorsque je fais un print_r des données récupéré de mon formulaire, tout est vide :

Code:

[lang=php]
print_r($formCommande->getData());

Affichage :

Code:

Custom\Model\Commande Object ( [id_commande] => [nom_pizza] => [sauce_pizza] => [taille_pizza] => [ingredients] => [desserts] => [boissons] => [total] => [creation] => [paye] => [dbAdapter:protected] => [columns:protected] => Array ( [0] => id_commande [1] => nom_pizza [2] => sauce_pizza [3] => taille_pizza [4] => ingredients [5] => dessers [6] => boissons [7] => total [8] => creation [9] => paye ) )

Hors ligne

 

#19 19-03-2014 18:59:35

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

j'ai l'impression que $formCommande->getData() n'arrive pas à récupérer les données des éléments définis dans le FieldSet.

Pourtant un print_r($_POST) affiche bien tout

Hors ligne

 

#20 20-03-2014 09:22:04

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

Tu peux mettre le code de ton formulaire, de ton fieldset et de ton entité stp wink.

Hors ligne

 

#21 20-03-2014 11:43:18

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Mon entité Commande.php :

Code:

[lang=php]
<?php
namespace Custom\Model;

use Zend\Db\Adapter\AdapterInterface;

class Commande
{
    public $id_commande;
    public $nom_pizza;
    public $sauce_pizza;
    public $taille_pizza;
    public $ingredients;
    public $desserts;
    public $boissons;
    public $total;
    public $creation;
    public $paye;
    protected $dbAdapter;
    
    public function exchangeArray($data)
    {
        $this->id_commande = isset($data['id_commande']) ? $data['id_commande'] : null;
        $this->nom_pizza = isset($data['nom_pizza']) ? $data['nom_pizza'] : null;
        $this->sauce_pizza = isset($data['sauce_pizza']) ? $data['sauce_pizza'] : null;
        $this->creation = isset($data['creation']) ? $data['creation'] : null;
        $this->paye = isset($data['paye']) ? $data['paye'] : null;
    }
    
    public function setDbAdapter(AdapterInterface $adapter)
    {
        $this->dbAdapter = $adapter;
    }
    
    public function getDbAdapter()
    {
        return $this->dbAdapter;
    }
}

Mon fichier CommandeTable.php :

Code:

[lang=php]
<?php
namespace Custom\Model;

use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Adapter\Exception\InvalidQueryException;
use Zend\Db\Sql\Select;

class CommandeTable
{
    /**
     * @var TableGateway
     */
    protected $tableGateway;

    public function __construct(TableGateway $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }

    public function getAdapter()
    {
        return $this->tableGateway->getAdapter();
    }
    
    public function getAll()
    {
        $select = new \Zend\Db\Sql\Select();
        $select->from($this->tableGateway->getTable());
        return $select;
    }
    
    public function fetchAll()
    {
        $select = $this->tableGateway->select();
        return $select;
    }


    public function getCommande($id)
    {
        $id  = (int)$id;
        $rowset = $this->tableGateway->select(array('id_commande' => $id));
        $row = $rowset->current();

        if (!$row) {
            throw new \Exception("Could not find row $id");
        }

        return $row;
    }
}

Mon fichier CommandeFieldset.php :

Code:

[lang=php]
<?php
namespace Front\Form;

use Custom\Model\Commande;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\Stdlib\Hydrator\ClassMethods as ClassMethodsHydrator;

class CommandeFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('commande');
        $this->setHydrator(new ClassMethodsHydrator(false))
        ->setObject(new Commande());

        $this->add(array(
                'name' => 'id_commande',
                'attributes' => array(
                        'type'  => 'hidden',
                ),
        ));
        
        
        $this->add(array(
            'type' => 'Zend\Form\Element\MultiCheckbox',
            'name' => 'desserts',
            'required' => false,
            'attributes' => array(
                'class' => 'desserts',
            ),
        ));
        
        $this->add(array(
            'name' => 'nom_pizza',
            'attributes' => array(
                'type'  => 'text',
                'required' => true,
                'placeholder' => 'Le nom de votre pizza',
                'class' => 'nom',
            ),
        ));
        
        $this->add(array(
                'name' => 'total',
                'type' => 'hidden',
                'attributes' => array(
                        'required' => true,
                        'class' => 'total'
                )
        ));
    }

    /**
     * @return array
     \*/
    public function getInputFilterSpecification()
    {
                
                'desserts' => array(
                        'required' => false,
                ),
                
                'boissons' => array(
                        'required' => false,
                ),
        );
    }
}

Le fichier AjouterCommandeForm.php :

Code:

[lang=php]
<?php
namespace Front\Form;

use Zend\Form\Form;
use Zend\InputFilter\InputFilter;
use Zend\Stdlib\Hydrator\ClassMethods as ClassMethodsHydrator;

class AjouterCommandeForm extends Form
{
    public function __construct()
    {
        parent::__construct('ajouter_commande');

        $this->setAttribute('method', 'post')
             ->setHydrator(new ClassMethodsHydrator(false))
             ->setInputFilter(new InputFilter());

        $this->add(array(
            'name' => 'commande',
            'type' => 'Front\Form\CommandeFieldset',
            'options' => array(
                'use_as_base_fieldset' => true
            )
        ));

        $this->setValidationGroup(
                array(
                        'commande' => array(
                                'id_commande',
                                'taille_pizza',
                                'sauce_pizza',
                                'ingredients',
                                'nom_pizza',
                                'desserts',
                                'boissons',
                                'total',
                        ),
                        'csrf',
                        'submit',
                )
        );
        
        $this->add(array(
            'name' => 'submit',        // Nom du champ
            'type' => 'Submit',        // Type du champ
            'attributes' => array(     // On va définir quelques attributs
                'value' => 'Ajouter',  // comme la valeur
                'id' => 'submit',      // et l'id
            ),
        ));
    }
}

Mon action indexAction() de mon IndexController.php :

Code:

[lang=php]
    public function indexAction()
    {
        $formCommande = new AjouterCommandeForm();
        $request = $this->getRequest();
        $commande = new Commande();
        $formCommande->bind($commande);
        
        // récupère toutes les tailles de pizza
        $tabOptionTaille = $this->taillePizzaTable->getAllOrder('id_taille');
        
        if ($request->isPost()) {
            $formCommande->setData($request->getPost());
            
            if ($formCommande->isValid()) {   
                     //print_r($formCommande->getData())
             // print_r($_POST);
                     $this->commandeTable->saveCommande($formCommande->getData());                      
            } 
        }
        
        return new ViewModel(
                array(
                    'form' => $formCommande,
                )
        );
    }

Un print_r($formCommande->getData()) affiche :

Code:

Custom\Model\Commande Object ( [id_commande] => [nom_pizza] => [sauce_pizza] => [taille_pizza] => [ingredients] => [desserts] => [boissons] => [total] => [creation] => [paye] => [dbAdapter:protected] => )

Un print_r($_POST) affiche :

Code:

Array ( [commande] => Array ( [id_commande] => [taille_pizza] => Petite/6 [sauce_pizza] => Sauce blanche/1 [ingredients] => Array ( [0] => viande de kébab/0.60 [1] => oignons/0.10 ) [nom_pizza] => kebab [boissons] => Array ( [0] => fanta/1.50 [1] => coca cola/1.50 ) [desserts] => Array ( [0] => moelleux au chocolat/2 ) [total] => 12.7 ) [csrf] => f272aa7b110b7230b3608c8948ec1546 [submit] => Ajouter )

Voici l'exception affichée lorsque je valide le formulaire :
    SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'nom_pizza' cannot be null

Je pense que c'est du au faite que les données qui sont $formCommande->getData() sont null

Dernière modification par romsVLM (20-03-2014 16:58:50)

Hors ligne

 

#22 20-03-2014 12:00:46

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Problème avec la validation d'un formulaire

Non $formCommande->getData() ne retourne pas null mais un objet vide. Ca veut dire que l'objet n'a pas été hydrater. Pour résoudre le problème fais des getters et setters. Ca devrait fonctionner wink.
Tu risque aussi de rencontrer un problème car tes variables sont avec des "_" et je sais plus exactement ce qu'il faut faire si tu dois en tenir compte dans les getters/setters ou s'il te suffit de faire des variables qui respectent le camelCase wink !

Hors ligne

 

#23 20-03-2014 12:07:29

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

Je dois mettre des getters et setters dans mon entité Commande.php pour chacun des attributs ?

Hors ligne

 

#24 20-03-2014 12:33:19

romsVLM
Membre
Date d'inscription: 23-01-2014
Messages: 89

Re: Problème avec la validation d'un formulaire

J'ai rajouté les setters et getters, mon tableau est bien rempli maintenant. Merci beaucoup.

Par contre si ça ne te dérange pas, peux tu me donner quelques explications ?

Pourquoi sans getters et setters, mon objet n'a pas été hydraté ? N'étais ce pas le rôle de ExchangeArray($data) ?

Hors ligne

 

#25 20-03-2014 12:43:31

flobrflo
Membre
Lieu: Marseille
Date d'inscription: 26-04-2013
Messages: 376

Re: Problème avec la validation d'un formulaire

Orkin, tu a le droit d'utiliser les "_" dans tes variables.

romsVLM le exchangeArray te permet le "set" de l'objet complet. Mais tu ne peu pas les récupérer ensuite si tu ne met pas les getters.

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