Colonnes de recherche perso dans le filter de l'admin generator, avec Doctrine

Comment faire pour filtrer l’affichage dans l’admin generator lorsqu’on a à faire à un champs qui n’est pas dans la table considérée ?

Un exemple ici : j’ai des utilisateurs, avec la table User, mais j’ai aussi une table sfGuardUser.

Ma table User contient les infos globales de mes utilisateurs, alors que la table sfGuardUser contient les informations d’identification et permet également de récupérer les infos sur les permissions, les groupes, etc.

Voilà le problème : j’ai dans le listing de mes utilisateurs ajouté la colonne “Administrateur ?”, indiquant si l’utilisateur est admin ou non (vous l’aurez compris…), pour cela il m’a suffit de rajouter la méthode getIsAdmin() dans ma classe User.class.php (lib/model/doctrine/User.class.php), et le champs is_admin dans le generator.yml de mon module user dans le backend (apps/backend/modules/user/config/generator.yml). (cf jobeet n°12)

Pour le filter le problème est un tout petit peu plus complexe : il n’utilise pas la classe pour filtrer l’affichage, et n’utilisera donc pas la méthode getIsAdmin().

Pourquoi ?

Par ce qu’il ne fait que générer une requete Doctrine_Query executée dans l’action.

Il y’aura donc ici 3 choses à faire :

  1. ajouter le champs is_admin dans le formulaire du filter
  2. surcharger la méthode getFields() (sert à récupérer les valeurs du formulaire)
  3. ajouter la méthode qui modifie la requête

1) Ajout du champs is_admin (lib/form/filter/doctrine/UserFormFilter.class.php)
Le formulaire du filtre n’est rien de mieux qu’un formulaire sfFormFilter, on a donc déjà vu comment ça marche

    $this->validatorSchema['is_admin'] = new sfValidatorBoolean(array('required' => false), array());
    $this->widgetSchema['is_admin'] = new sfWidgetFormSelect(array(
      'choices' => array('' => '', true => 'oui', false => 'non')
      ));

Pensez aussi à créer le label correspondant.

2) Surcharge de getFields() (lib/form/filter/doctrine/UserFormFilter.class.php)

  public function getFields()
  {
    return array_merge(array('is_admin' => 'IsAdmin'), parent::getFields());
  }

3) Ajout de la méthode de modification de la requête :

  public function addIsAdminColumnQuery(Doctrine_Query $q, $field,$value)
  {
    if($value) //je cherche à trouver les admins
    {
      $a = $q->getRootAlias();
      $q->innerJoin($a . '.sfGuardUser u')
        ->innerJoin('u.sfGuardUserPermission up')
        ->innerJoin('up.sfGuardPermission p')
        ->andWhere('p.name = ?', 'admin');
    }

    if(!$value) //si je cherche les non admins
    {
      $a = $q->getRootAlias();
      $q->innerJoin($a . '.sfGuardUser u')
        ->innerJoin('u.sfGuardUserPermission up')
        ->innerJoin('up.sfGuardPermission p')
        ->andWhere('p.name = ?', 'member');
    }
    return $q;
  }

Essayons de voir le plan général :

– la méthode à ajouter doit s’appeler add*nom de la colonne*ColumnQuery
– elle prend en paramètres :

– la requête déjà défini par les autres champs du filtre, si aucun champs n’est renseigné elle correspond à la
requête récupérant tous les objets en question (ici les utilisateurs)

– le nom du champs en question

– la valeur entrée dans le formulaire filter.

A vous de modifier ensuite la requête passée en paramètre pour filtrer vos résultats.
Et voilà !!

Voir l’étude de cas
Lire l’article
Voir le témoignage
Fermer