Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonsoir,
Je suis en train de créer un module admin, qui gère toute une couche d'ajout de droit, et de lier des utilisateur aux droits, aux permissions etc...
J'ai plusieurs question que je n'arrive pas à résoudre...
Pour le formulaire de mise à jour d'un role :
- J'ai un formulaire avec un element DoctrineSelect (+ attribut multiple et le tout géré dans la vue avec select2), qui va chercher tous les roles, comment lui faire dire de prendre tous les roles sauf celui qui est mis à jour ?
(L'id du role est passé en paramètre)
Voici mon champ de formulaire :
[lang=php] $this->add( array( 'name' => 'children', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Children', 'target_class' => 'Application\Entity\HierarchicalRole', 'property' => 'name', ), 'attributes' => array( 'multiple' => true, 'class' => 'select2 form-control', ), )
- D'autre part, quand je choisis mes rôles dans ce select, si j'en enlève un, il me les supprime tous.... y a vraiment un soucis avec l'hydration doctrine à ce niveau ou c'est moi qui fait pas les choses correctement ?
Par contre si j'en ajoute un sans en enlever il m'ajoute bien le nouveau.
Quelqu'un peut il me montrer une implémentation de la méthode remove comme elle est attendue par ce code :
https://github.com/doctrine/DoctrineMod … yValue.php
la mienne ici :
[lang=php] public function removeChildren(ArrayCollection $children) { foreach ($children as $child) { $this->children->clear(); } }
Je croyais que $children serait un tableau d’élément à supprimer mais apparemment ils estime que mes childrens ne sont pas les mêmes par rapport a ceux qui y étaient avant... du coup tout est supprimé.
Dernière modification par JGreco (09-01-2015 10:24:17)
Hors ligne
Salut,
tu fais un "clear" , et clear, bin sa enlève tout .
moi généralement je fais comme ça, je peux en supprimer un seul à la fois comme ça si je veux.
[lang=php] public function removeChild(Role $child) { $this->children->removeElement($child) } public function removeChildren(ArrayCollection $children) { foreach ($children as $child) { $this->removeChild($child); } }
d'autre part, avec les doctrineElement tu peux spécifier la fonction à utiliser sur le repistory de la classe :
https://github.com/doctrine/DoctrineMod … element.md
(voir l'exemple 3)
Tu crées donc une fonction qui retourne tout les rôles sauf celui dont le nom est indiqué en paramètre, et tu l'indiques dans l'options "find_method" de ton objectSelect
[lang=php] array( 'name' => 'children', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Children', 'target_class' => 'Application\Entity\HierarchicalRole', 'property' => 'name', 'is_method' => true, 'find_method' => array( 'name' => 'findAllExeptOne', 'params' => array( 'criteria' => array('roleId' => $roleId), ), )
voili voilou
Dernière modification par Splyf (16-12-2014 08:02:38)
Hors ligne
Merci splyf, c'est exactement ce que je cherchais. Je teste cela et je reviens vers toi si j'ai des questions, merci
Hors ligne
Merci pour le removeElement() ça marche niquel comme ça.
Et pour la méthode findAllExeptOne le problème c'est que je suis dans un Form/Fieldset ici, et que mon roleId n'est pas défini et je ne sais pas comment le récupérer.... une idée?
Hors ligne
Bonjour,
retour de vacances j'ai pas eu le temps de me repencher dessu depuis mes derniers essais, j'ai toujours pas la solution pour passer le roleID de ma route au formulaire pour que la méthode findAllExeptOne puisse fonctionner :
[lang=php] public function findAllExeptOne($roleID) { $query = $this->createQueryBuilder('r'); $query->select('r')->where($query->expr()->notIn('r.id', $roleID)); return $query->getQuery()->getResult(); }
Et donc appellé dans ma classe fieldset du formulaire...
[lang=php] $this->add( array( 'name' => 'children', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Children', 'target_class' => 'Application\Entity\HierarchicalRole', 'property' => 'name', 'is_method' => true, 'find_method' => array( 'name' => 'findAllExeptOne', 'params' => array( 'criteria' => array('roleId' => $this->get('id')->getValue()), ), ) ), 'attributes' => array( 'multiple' => true, 'class' => 'select2 form-control', ), ) );
Je n'arrive pas a trouver un truc propre pour faire marcher cela... Une idée svp je sèche complet :s, merci
Hors ligne
Plop, à part une requête en ajax je ne vois pas trop comment tu pourrais faire autrement. Tu peux essayer de créer le formulair en ajoutant tes éléments dans initBis($idToExclude) par exemple et quand tu récupères ton formulaire depuis le FormElementManager tu appèles la fonction initBis en passant ton $id à exclure et c'est dans initBis() que tu fais tes $this->add() etc ...
Hors ligne
Bonjour,
Voici un lien que j'avais pas vu au fil de mes recherches, est-ce propre comme solution ?
C'était une de mes idées, mais je n'avais pas réussi à trouver le meilleur moyen de l'implémenter.
http://stackoverflow.com/questions/2395 … ramework-2
Hors ligne
Je trouve pas ça super propre de récupérer la requête dans la factory après ça peut résoudre ton problème.
Pour le premier cas d'appeler init après avoir récupérer l'instance ça sert à rien puisque la fonction init() est appelée automatiquement par le FormElementManager. C'est pourquoi je te proposais d'avoir une fonction init() vide et d'avoir une fonction initBis() qui prend des paramètres par exemple. De cette manière tu peux l'appeler dans ton contrôleur en passant les paramètres dont tu as besoin.
Hors ligne
Oui, en effet ta solution semble plus adaptée, je vais l'essayer dans la journée. Merci en tous cas
Hors ligne
Bonjour,
J'ai testé cette solution, hélas un nouveau soucis est survenu. L'hydrator saute pour une raison que j'ignore.
Ceci est mon action du contrôleur,
[lang=php] public function updateRoleAction() { $view = new ViewModel(); $request = $this->getRequest(); $form = $this->getServiceLocator()->get('formElementManager')->get('Admin\Form\UpdateRole'); $fieldset = $this->getServiceLocator()->get('formElementManager')->get('Admin\Form\Fieldset\AddFieldset'); $id = $this->params('id'); $fieldset->initBis($id); $form->add($fieldset, array('name' => 'updateRole')); $role = $this->rights->getRole($id); $form->bind($role); if ($request->isPost()) { $form->setData($request->getPost()); if ($form->isValid()) { $this->flashMessenger()->setNamespace('success')->addMessage('Your role has been updated'); $role = $form->getData(); $this->rights->updateRole($role); return $this->redirect()->toRoute('backoffice/rights'); } $this->flashMessenger()->setNamespace('danger') ->addMessage('An error occured please check informations below fields form more informations.'); } $view->setVariable('form', $form); $view->setVariable('id', $id); return $view; }
J'ai commenté l'ajout du fieldset dans ma Classe 'Admin\Form\UpdateRole'
Voici la classe Fieldset et son implémentation en rapport avec ton idée
[lang=php] namespace Admin\Form\Fieldset; use DoctrineModule\Persistence\ObjectManagerAwareInterface; use DoctrineModule\Persistence\ProvidesObjectManager as ProvidesObjectManagerTrait ; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; use Application\Entity\HierarchicalRole; class AddRoleFieldset extends Fieldset implements ObjectManagerAwareInterface, InputFilterProviderInterface { use ProvidesObjectManagerTrait; public function init() { } public function initBis($roleID) { $this->setHydrator(new DoctrineHydrator($this->getObjectManager(), 'Application\Entity\HierarchicalRole')) ->setObject(new HierarchicalRole()); $this->add( array( 'name' => 'id', 'type' => 'hidden', ) ); $this->add( array( 'name' => 'name', 'type' => 'Zend\Form\Element\Text', 'options' => array( 'label' => 'Role\'s name', 'comments' => 'Role name' ), 'attributes' => array( 'class' => 'form-control', ), ) ); $this->add( array( 'name' => 'children', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Children', 'target_class' => 'Application\Entity\HierarchicalRole', 'property' => 'name', 'is_method' => true, 'find_method' => array( 'name' => 'findAllExeptOne', 'params' => array( 'roleID' => $roleID, ), ) ), 'attributes' => array( 'multiple' => true, 'class' => 'select2 form-control', ), ) ); $this->add( array( 'name' => 'permissions', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Permissions', 'target_class' => 'Application\Entity\Permission', 'property' => 'name', ), 'attributes' => array( 'multiple' => true, 'class' => 'select2 form-control', ), ) ); } /** * Set requirements for validation * @return array */ public function getInputFilterSpecification() { return array( 'name' => array( 'required' => true, 'filters' => array( array('name' => 'StripTags'), array('name' => 'StringTrim'), ), ), 'children' => array( 'required' => true, 'filters' => array( array('name' => 'StripTags'), array('name' => 'StringTrim'), ), ), 'permissions' => array( 'required' => true, 'filters' => array( array('name' => 'StripTags'), array('name' => 'StringTrim'), ), ), ); } }
L'erreur obtenu est :
[lang=php] Zend\Stdlib\Hydrator\ArraySerializable::extract expects the provided object to implement getArrayCopy()
Et le stack trace :
[lang=php] #0 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Form\Fieldset.php(641): Zend\Stdlib\Hydrator\ArraySerializable->extract(Object(Application\Entity\HierarchicalRole)) #1 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Form\Form.php(881): Zend\Form\Fieldset->extract() #2 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Form\Form.php(303): Zend\Form\Form->extract() #3 C:\wamp\www\jonathan\module\Admin\src\Admin\Controller\RightsController.php(48): Zend\Form\Form->bind(Object(Application\Entity\HierarchicalRole)) #4 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Mvc\Controller\AbstractActionController.php(83): Admin\Controller\RightsController->updateRoleAction() #5 [internal function]: Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent)) #6 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\EventManager\EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent)) #7 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\EventManager\EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure)) #8 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Mvc\Controller\AbstractController.php(117): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure)) #9 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Mvc\DispatchListener.php(114): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request), Object(Zend\Http\PhpEnvironment\Response)) #10 [internal function]: Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent)) #11 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\EventManager\EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent)) #12 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\EventManager\EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure)) #13 C:\wamp\www\jonathan\vendor\zendframework\zendframework\library\Zend\Mvc\Application.php(313): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure)) #14 C:\wamp\www\jonathan\public\index.php(17): Zend\Mvc\Application->run() #15 {main}
La ligne 48 du stack trace #3 concerne la ligne dans mon controleur qui fait
[lang=php] $form->bind($role);
Voilà si quelqu'un à une idée
Hors ligne
Salut, ça aurait été bien de mettre le formulaire et tes entités aussi mais bon ...
Déjà pour le fieldset t'as une fonction init() vide ça sert un peu à rien les fonctions vides . Tu peux par contre mettre la définition de l'hydrateur dans la fonction init(). En gros ce que je t'avais dit de faire c'est de faire un fieldset normal sauf l'ajout de l'élément qui nécessite ton paramètre dans la fonction initBis().
Après je pense pas que ça changera grand chose.
Autre chose dans ton formulaire tu utilises le fields en tant que base fieldset, là à aucun moment tu lui dis de faire ça donc t'as pas reproduit la même situation .
Hors ligne
Ca marche !!!!
Enfin ! merci beaucoup !
Voici en gros la solutions :
Le controlleur :
[lang=php] public function updateRoleAction() { $view = new ViewModel(); $request = $this->getRequest(); $form = $this->getServiceLocator()->get('formElementManager')->get('Admin\Form\UpdateRole'); $fieldset = $this->getServiceLocator()->get('formElementManager')->get('Admin\Form\Fieldset\AddFieldset'); $fieldset->setUseAsBaseFieldset(true); // ça marche mieux avec ça en effet ! $id = $this->params('id'); $fieldset->initBis($id); $form->add($fieldset, array('name' => 'updateRole')); $role = $this->rights->getRole($id); $form->bind($role); if ($request->isPost()) { $form->setData($request->getPost()); if ($form->isValid()) { $this->flashMessenger()->setNamespace('success')->addMessage('Your role has been updated'); $role = $form->getData(); $this->rights->updateRole($role); return $this->redirect()->toRoute('backoffice/rights'); } $this->flashMessenger()->setNamespace('danger') ->addMessage('An error occured please check informations below fields form more informations.'); } $view->setVariable('form', $form); $view->setVariable('id', $id); return $view; }
La méthode initBis
[lang=php] public function initBis($roleID) { $this->add( array( 'name' => 'children', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Children', 'target_class' => 'Application\Entity\HierarchicalRole', 'property' => 'name', 'is_method' => true, 'find_method' => array( 'name' => 'findAllExeptOne', 'params' => array( 'roleID' => $roleID, ), ) ), 'attributes' => array( 'multiple' => true, 'class' => 'select2 form-control', ), ) ); }
Et notre méthode init de base :
[lang=php] public function init() { $this->setHydrator(new DoctrineHydrator($this->getObjectManager(), 'Application\Entity\HierarchicalRole')) ->setObject(new HierarchicalRole()); $this->add( array( 'name' => 'id', 'type' => 'hidden', ) ); $this->add( array( 'name' => 'name', 'type' => 'Zend\Form\Element\Text', 'options' => array( 'label' => 'Role\'s name', 'comments' => 'Role name' ), 'attributes' => array( 'class' => 'form-control', ), ) ); $this->add( array( 'name' => 'permissions', 'type' => 'DoctrineModule\Form\Element\ObjectSelect', 'options' => array( 'object_manager' => $this->getObjectManager(), 'label' => 'Permissions', 'target_class' => 'Application\Entity\Permission', 'property' => 'name', ), 'attributes' => array( 'multiple' => true, 'class' => 'select2 form-control', ), ) ); }
De là les possibilité sont infinies, c'est assez intéressant !
Hors ligne