Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > symfony
symfony Forum d'entraide sur le framework PHP symfony. Avant de poster : cours symfony et FAQ symfony
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 07/02/2012, 15h47   #1
Membre régulier
 
Avatar de kéraunos
 
Homme
Inscription : janvier 2005
Messages : 157
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : janvier 2005
Messages : 157
Points : 71
Points : 71
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 :
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 :
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.
kéraunos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2012, 17h19   #2
Membre chevronné
 
Avatar de kenny.kev
 
Homme
Inscription : janvier 2007
Messages : 577
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : France, Indre et Loire (Centre)

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

Informations forums :
Inscription : janvier 2007
Messages : 577
Points : 692
Points : 692
Envoyer un message via MSN à kenny.kev
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 :
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();
kenny.kev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2012, 18h13   #3
Membre régulier
 
Avatar de kéraunos
 
Homme
Inscription : janvier 2005
Messages : 157
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : janvier 2005
Messages : 157
Points : 71
Points : 71
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.
kéraunos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2012, 18h50   #4
Membre chevronné
 
Avatar de kenny.kev
 
Homme
Inscription : janvier 2007
Messages : 577
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : France, Indre et Loire (Centre)

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

Informations forums :
Inscription : janvier 2007
Messages : 577
Points : 692
Points : 692
Envoyer un message via MSN à kenny.kev
tu écris ça :
Code :
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.
kenny.kev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2012, 23h56   #5
Membre régulier
 
Avatar de kéraunos
 
Homme
Inscription : janvier 2005
Messages : 157
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : janvier 2005
Messages : 157
Points : 71
Points : 71
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 :
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.
kéraunos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 11h22   #6
Futur Membre du Club
 
Inscription : août 2009
Messages : 24
Détails du profil
Informations forums :
Inscription : août 2009
Messages : 24
Points : 18
Points : 18
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 :
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 :
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);
 
}
ufretin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 14h00   #7
Membre chevronné
 
Avatar de kenny.kev
 
Homme
Inscription : janvier 2007
Messages : 577
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : France, Indre et Loire (Centre)

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

Informations forums :
Inscription : janvier 2007
Messages : 577
Points : 692
Points : 692
Envoyer un message via MSN à kenny.kev
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.
kenny.kev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 17h45   #8
Membre régulier
 
Avatar de kéraunos
 
Homme
Inscription : janvier 2005
Messages : 157
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : janvier 2005
Messages : 157
Points : 71
Points : 71
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 :
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 :
$this->widgetSchema['famille_id'] = new sfWidgetFormFilterInput(array('with_empty' => false));
par
Code :
$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.
kéraunos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 18h03   #9
Membre chevronné
 
Avatar de kenny.kev
 
Homme
Inscription : janvier 2007
Messages : 577
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : France, Indre et Loire (Centre)

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

Informations forums :
Inscription : janvier 2007
Messages : 577
Points : 692
Points : 692
Envoyer un message via MSN à kenny.kev
Pour le premier point tu as essayé sans mettre
Code :
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.
kenny.kev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 18h16   #10
Membre régulier
 
Avatar de kéraunos
 
Homme
Inscription : janvier 2005
Messages : 157
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : janvier 2005
Messages : 157
Points : 71
Points : 71
En fait, j'ai trouvé une solution pour la 2ème problématique, dans la méthode surchargée (cf. message d'ufretin) :

Code :
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 :
1
2
3
4
5
 
    $rootAlias = $query->getRootAlias();
 
    if ($value)
        $query->andWhere($rootAlias . '.Famille.famille_nom = ?', $value);
kéraunos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 09h41   #11
Membre habitué
 
Inscription : juin 2006
Messages : 488
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 488
Points : 116
Points : 116
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
erictomcat est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 18h48.


 
 
 
 
Partenaires

Hébergement Web