IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Changer le type de champ d'un filtre


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Changer le type de champ d'un filtre
    Bonjour à tous,

    Dans un module d'administration créé à l'aide de la commande doctrine:generate-admin, je dispose d'une liste d'objets que je peux filtrer.

    Dans mon cas (simplifié), je veux filtrer des Personnes en fonction de leurs Familles. Chaque Personne appartient à une et une seule Famille. Dans le modèle physique de données, cela se traduit par une clé étrangère famille_id dans la table Personne faisant référence à la table Famille.

    Par défaut, voici le widget et le validateur de filtre créés par Symfony :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    abstract class BasePersonneFormFilter extends BaseFormFilterDoctrine {
     
      public function setup()
      {
        $this->setWidgets(array(
          'famille_id' => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('Famille'), 'add_empty' => true)),
          //[...]
        ));
     
        $this->setValidators(array(
          'family_id' => new sfValidatorDoctrineChoice(array('required' => false, 'model' => $this->getRelatedModelName('Famille'), 'column' => 'id')),
          //[...]
        ));
        //[...]
      }
      //[...]
    }
    Dans le filtre, cela donne une liste déroulante avec toutes les familles de la table Famille. Or, je voudrais simplement un champ "input text" où l'on puisse rentrer le nom de famille (champ famille_nom de la table Famille) que l'on veut. Et obtenir une liste de 0 résultat si on se plante. Le truc normal.

    J'ai essayé bêtement de remplacer par des choses comme new sfWidgetFormFilterInput(array('with_empty' => false)) et new sfValidatorPass(array('required' => false)), mais ça n'a pas fonctionné :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    500 | Internal Server Error | Doctrine_Connection_Mysql_Exception
    SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
     
    at() in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php line 1082
    at Doctrine_Connection->rethrowException(object('PDOException'), object('Doctrine_Connection_Statement'))
    at Doctrine_Connection_Statement->execute(array('text' => 'FAMILLE_1'))
    [...]
    Sauriez-vous m'aiguiller ?

    Merci.

  2. #2
    Membre émérite Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Par défaut
    Alors on ne touche surtout pas au fichier Base....FromFilter.class.php.

    Les seuls fichiers que tu dois modifier sont les ...FromFilter.class.php qui sont dans lib/filter/doctrine et uniquement ceux là.

    Pour les modifier c'est pour les forms standard.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $this->widgetSchema['logo'] = new sfWidgetFormInputFileEditable(array(
           'label'     => 'Company logo',
           'file_src'  => '/uploads/jobs/'.$this->getObject()->getLogo(),
           'is_image'  => true,
           'edit_mode' => !$this->isNew(),
           'template'  => '<div>%file%<br />%input%<br />%delete% %delete_label%</div>',     ));
           $this->validatorSchema['logo_delete'] = new sfValidatorPass();

  3. #3
    Invité
    Invité(e)
    Par défaut
    Salut,

    Ok. Pour les classes mères qui commencent par "Base...", je savais. J'ai fait un raccourci dans mon message. Mais c'est toujours utile de le rappeler.

    En revanche, je ne comprends pas comment résoudre mon problème à partir de ton exemple.

  4. #4
    Membre émérite Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Par défaut
    tu écris ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $this->widgetSchema['nom de ton champ'] = new sfWidgetFormInput();
    $this->validatorSchema['nom de ton champ'] = new sfValidatorPass(array('required' => false));
    Comme écrit sur la doc symfony.

  5. #5
    Invité
    Invité(e)
    Par défaut
    kenny.kev,

    J'apprécie tes efforts pour me répondre. Mais il semble que ta dernière réponse soit un peu trop lapidaire pour être courtoise. Si je t'insupporte, tu n'es pas obligé de me venir en aide. Merci.

    Peux-tu donner un lien lorsque tu parles de doc symfony ? Sans être expert, (loin de là !), je ne suis pas totalement ignare : j'ai cherché et ai trouvé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sfWidgetFormFilterInput represents an HTML input tag used for filtering text.
    C'est une source qui se défend : la doc PHP de la classe sfWidgetFormFilterInput.

    Donc, dans un premier temps : pourquoi ne pas utiliser les classes de widgets et validateurs pour formulaires de filtres mais utiliser celles de formulaires tout court ? Je ne dis pas que tu as tort, je me pose juste la question.

    Dans un second temps : ta suggestion ne résout pas mon problème, exposé en détail dans mon premier message. Il ne s'agit pas de filtrer le champ famille.id mais le champ famille.famille_nom. Et ce à partir de la liste du module Personne. Tout en sachant que la table Personne fait référence au champ famille.id à l'aide d'une clé étrangère personne.famille_id.
    Bref, par défaut, avec ta solution, l'utilisateur est obligé de rentrer un id (entier naturel). Rentrer un nom de famille (texte) ne donne rien.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Août 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 25
    Par défaut
    En effet, dans la partie form filter, il faut bien utiliser des "sfWidgetFormFilterInput" par exemple, et non des "sfWidgetFormInput"

    Quoi qu'il en soit, tu as deux problématiques:
    1 - remplacer ton select par un input text
    2 - faire en sorte que l'utilisateur tape un nom, et pas un id

    D'une part, entre parenthèse, je te conseillerais peut-être d'utiliser un sfWidgetFormJQueryAutocompleter (disponible dans les plugins de Symfo). Il s'agit d'une zone de texte qui sort en Ajax les valeurs de ta table (un autocompleter quoi). C'est simple, rapide et efficace.

    Si tu souhaites tout de même passer par un input simple, il te faudra:

    - pour le 1), remplacer ton widget choice dans ton FormFilter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $this->widgetSchema['famille_id'] = new sfWidgetFormFilterInput(array('with_empty' => false));
    $this->validatorSchema['famille_id'] = new sfValidatorPass(array('required' => false));
    - pour le 2), surcharger le filtrage en lui-même. Il faut pour cela rajouter une méthode dans ce même fichier de form portant le nom de ton champ, et spécifiant la règle de filtrage, comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public function addFamilleIdColumnQuery(Doctrine_Query $query, $field, $value)
    {
       //Pour le xxxx tu peux utiliser $query->getRootAlias() pour récupérer l'alias racine de ta requete
      if( $value )
          $query->andWhere('xxxx.famille_id = ?', $value);
     
    }

  7. #7
    Membre émérite Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Par défaut
    kéraunos,

    Je m'excuse pour mon impolitesse. Ça ne me soûle pas de te répondre. Alors quelque soit le coté (l'admin-generator ou bien le front) toutes les règles s'applique pour les 2.
    Voici le lien http://www.symfony-project.org/jobee...Doctrine/en/10.

    En revanche oui mon exemple est faux car il faut bien ...FromFilterInput() pour l'admin-generator.
    J'aurais du aussi te donnée l'indication qu'il fallait faire un validateur particulier qui lui cherchera le id correspondant au nom sinon retourne une erreur.

    ufretin à aussi proposé une solution assez pratique, bien entendu si tu utilise Prototype et non jQuery tu as la meme classe pour lui. Par contre si tu utilise une autre lib js, je ne sais pas.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Merci à vous deux pour vos réponses.

    - Pour la 1ère problématique (remplacer le select par un input text) :

    L'objectif premier est seulement de changer le type de champ : avoir un champ texte dans lequel je puisse rentrer l'id d'une famille.
    Ok.
    Lorsque j'utilise le widget et le validator que tu proposes ufretin, cela ne fonctionne pas. Voici l'erreur (j'ai rentré 1, et la famille ayant l'id 1 existe bel et bien dans ma base) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    500 | Internal Server Error | Doctrine_Connection_Mysql_Exception
    SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
     
    stack trace
     
    1. at ()
        in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php line 1082
    2. at Doctrine_Connection->rethrowException(object('PDOException'), object('Doctrine_Connection_Statement'))
    in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Statement.php line 269
    3. at Doctrine_Connection_Statement->execute(array('text' => '1'))
    in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php line 1006
    4. at Doctrine_Connection->execute('SELECT COUNT(*) AS num_results FROM (SELECT p.id FROM personne p LEFT JOIN famille f ON p.famille_id = f.id WHERE p.famille_id = ? GROUP BY p.id) dctrn_count_query', array('text' => '1')) in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php line 800
    5. at Doctrine_Connection->fetchAll('SELECT COUNT(*) AS num_results FROM (SELECT p.id FROM personne p LEFT JOIN famille f ON p.famille_id = f.id WHERE p.famille_id = ? GROUP BY p.id) dctrn_count_query', array('text' => '1'))
    in SF_ROOT_DIR/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query.php line 2150
    [...]

    En revanche, si je remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->widgetSchema['famille_id'] = new sfWidgetFormFilterInput(array('with_empty' => false));
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->widgetSchema['famille_id'] = new sfWidgetFormInput();
    alors ça fonctionne.

    Ce qui semble aller dans le sens de ce que kenny.kev conseillait en premier lieu.

    Pourquoi l'utilisation de la classe sfWidgetFormFilterInput pose-t-elle problème ?


    - Pour la 2ème problématique (faire en sorte que l'utilisateur tape un nom au lieu d'un id) :

    J'utilise :
    - le widget sfWidgetFormInput() (cf. ci-dessus)
    - le validateur sfValidatorPass() (cf. message d'ufretin)
    - et la surcharge de filtre proposée par ufretin

    Or, le filtre prend toujours en compte l'id de la famille et pas le nom. Quand je rentre un nom, je n'ai aucun résultat.
    En fait, ufretin, où est le lien avec le champ famille.famille_nom dans ta solution ?

    Par exemple, si je veux que l'utilisateur tape une origine (je dis n'importe quoi, c'est pour illustrer), il faudrait alors filtrer en fonction du champ origine de la table famille, et pas en fonction du champ famille_nom, ni du champ id. Donc il faut bien que cette information apparaisse au moins une fois, non ?

    Ici, j'ai l'impression qu'on sélectionne les personnes dont le champ famille_id correspond à ce qu'a rentré l'utilisateur. Or, je veux qu'on sélectionne les personnes dont la clé étrangère famille_id renvoie à une famille qui a comme champ famille_nom ce qu'a rentré l'utilisateur.

  9. #9
    Membre émérite Avatar de kenny.kev
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 646
    Par défaut
    Pour le premier point tu as essayé sans mettre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array('with_empty' => false)
    dans le sfWidgetFormFilterInput ? Normalement il faut rien.

    Pour le 2ème point, voilà un lien qui devrais répondre à tes questions : http://www.e-glop.net/main/Petit_gui...ormExtraPlugin

    C'est du js au final, donc normalement tu peux ajouter tous les champs permettant de filtrer.

  10. #10
    Invité
    Invité(e)
    Par défaut
    En fait, j'ai trouvé une solution pour la 2ème problématique, dans la méthode surchargée (cf. message d'ufretin) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        $rootAlias = $query->getRootAlias();
     
        if ($value)
            $query->leftJoin ($rootAlias . '.Famille sa_famille')
                      ->andWhere('sa_famille.famille_nom = ?', $value);
    Pour la 1ère problématique : toujours pas d'explication.

    Edit1 : kenny.kev : je vais essayer. Merci pour le lien, j'irai voir.

    Edit2 : Eh bien non ça ne fonctionne pas non plus sans l'option with_empty.


    Edit3 :

    Il y a même plus simple (pour la 2ème problématique) grâce à la puissance de Doctrine :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        $rootAlias = $query->getRootAlias();
     
        if ($value)
            $query->andWhere($rootAlias . '.Famille.famille_nom = ?', $value);
    Dernière modification par Invité ; 08/02/2012 à 18h37.

  11. #11
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    534
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 534
    Par défaut
    attention sfWidgetFormFilterInput renvoie un array alors que sfWidgetFormInput renvoie une variable.
    Je me suis fait avoir.
    Si tu recherche mes post sur le site tu devrai trouver

  12. #12
    Membre averti
    Inscrit en
    Avril 2002
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Avril 2002
    Messages : 15
    Par défaut
    Bonjour,
    Ma réponse ne te servira peut-être pas personnellement depuis le temps mais pour d'autres comme moi qui tomberais sur ce message. Je me permet de changer d'exemple pour ne pas faire de mauvais copier/coller.

    Dans la classe "Base...FormFilter.class.php", on trouve, en plus des widgets et validateurs que l'on connais bien pour les forms :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public function getFields()
    {
        return array(
          'id'          => 'Number',
          'campagne_id' => 'ForeignKey',
          'boutique'    => 'Text',
        );
    }
    Donc lorsque l'on choisi de changer le widget d'un élément, il faut aussi changer son type.
    J'ai basculé un champ texte en select ('boutique') et un champ select "clé étrangère" en texte ('campagne_id' devient 'campagne').

    Dans le fichier "Base...FormFilter.class.php" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public function setup()
    {
        $this->setWidgets(array(
          'campagne_id' => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('Campagne'), 'add_empty' => true)),
          'boutique'    => new sfWidgetFormFilterInput(array('with_empty' => false)),
        ));
        $this->setValidators(array(
          'campagne_id' => new sfValidatorDoctrineChoice(array('required' => false, 'model' => $this->getRelatedModelName('Campagne'), 'column' => 'id')),
          'boutique'    => new sfValidatorPass(array('required' => false)),
        ));
    }
     
    public function getFields()
    {
        return array(
          'id'          => 'Number',
          'campagne_id' => 'ForeignKey',
          'boutique'    => 'Text',
        );
    }
    Dans mon fichier "...FormFilter.class.php" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public function configure()
    {
      	$this->setWidget('boutique', new sfWidgetFormSelect(array('choices' => $shops)));
      	$this->setValidator('boutique', new sfValidatorChoice(array('required' => false, 'choices' => $shops)));
      	$this->setWidget('campagne', new sfWidgetFormFilterInput(array('with_empty' => false)));
      	$this->setValidator('campagne', new sfValidatorSchemaFilter('text', new sfValidatorString(array('required' => false))));
    }
     
    public function getFields()
    {
      	$fields = parent::getFields();
      	$fields['boutique'] = 'Enum';
      	$fields['campagne'] = 'Text';
      	return $fields;
    }
     
    public function addCampagneColumnQuery(Doctrine_Query $query, $field, $value)
    {
      	$rootAlias = $query->getRootAlias();
      	if ($value['text'])
      		$query->andWhere($rootAlias . '.Campagne.nom LIKE ?', '%'.$value['text'].'%');
    }
    J'attire votre attention sur 3 points :
    - un validateur différent des forms : sfValidatorSchemaFilter
    - bien paramétrer le type du champ
    - pour la fonction Query, je l'ai ajouté sur un champ texte, il faut donc aller chercher "$value['text']"

Discussions similaires

  1. Réponses: 10
    Dernier message: 14/08/2007, 22h27
  2. changer le type d'un champs d'une table = effacement des données ?
    Par pierre2410 dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 14/05/2007, 11h22
  3. Changer le type d'un champ via vba
    Par mat75019 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 02/10/2006, 17h42
  4. Changer le type d'un champ
    Par jean-pierre96 dans le forum Access
    Réponses: 1
    Dernier message: 17/05/2006, 16h50
  5. Probleme Alter - Changer le type d'un champ
    Par Yphon dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/09/2005, 13h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo