Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 14-12-2014 19:12:23

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

[Résolu]Gestion des droits Rbac, petit soucis

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 :

Code:

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

Code:

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


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#2 16-12-2014 08:01:09

Splyf
Membre
Date d'inscription: 24-10-2013
Messages: 115

Re: [Résolu]Gestion des droits Rbac, petit soucis

Salut,

tu fais un "clear" , et clear, bin sa enlève tout smile .
moi généralement je fais comme ça, je peux en supprimer un seul à la fois comme ça si je veux.

Code:

[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

Code:

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

Dernière modification par Splyf (16-12-2014 08:02:38)

Hors ligne

 

#3 16-12-2014 10:30:39

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

Merci splyf, c'est exactement ce que je cherchais. Je teste cela et je reviens vers toi si j'ai des questions, merci smile


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#4 16-12-2014 19:14:44

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

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?


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#5 05-01-2015 00:29:49

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

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 :

Code:

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

Code:

[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


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#6 05-01-2015 14:16:16

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

Re: [Résolu]Gestion des droits Rbac, petit soucis

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

 

#7 06-01-2015 09:47:59

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

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


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#8 06-01-2015 11:22:17

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

Re: [Résolu]Gestion des droits Rbac, petit soucis

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

 

#9 06-01-2015 11:24:39

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

Oui, en effet ta solution semble plus adaptée, je vais l'essayer dans la journée. Merci en tous cas smile


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#10 08-01-2015 08:57:11

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

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,

Code:

[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

Code:

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

Code:

[lang=php]
Zend\Stdlib\Hydrator\ArraySerializable::extract expects the provided object to implement getArrayCopy()

Et le stack trace :

Code:

[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

Code:

[lang=php]
$form->bind($role);

Voilà si quelqu'un à une idée


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#11 08-01-2015 11:52:59

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

Re: [Résolu]Gestion des droits Rbac, petit soucis

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 wink. 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 wink.

Hors ligne

 

#12 09-01-2015 09:48:33

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Gestion des droits Rbac, petit soucis

Ca marche !!!!
Enfin ! merci beaucoup !

Voici en gros la solutions :

Le controlleur :

Code:

[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

Code:

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

Code:

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


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

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