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 :

[Form] Réaliser un simple formulaire Entity Field Type [2.x]


Sujet :

Symfony PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut [Form] Réaliser un simple formulaire Entity Field Type
    Bonjour,

    Je débute complètement sur Symfony2 et je bloque sur des problemes de base. J'ai effectué une rapide recherche ici et surtout des recherches sur google mais j'ai pas encore réussi à résoudre mon soucis...

    Je vous expose mon problème. J'ai créé une entité Category et ai réussi à la mapper correctement avec Doctrine afin de créer la table correspondante sur ma base mysql.

    Cette table contient 3 champs: id, name et parent_id.

    Les champs id et name sont obligatoires, tandis que mon champ parent_id est optionnel: ce champ est valorisé si nous avons affaire a une sous catégorie, et doit rester vide si nous avons affaire à une catégorie principale.

    Voici le code de mon entité:

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
     
    <?php
    namespace XXXXBundle\Entity;
     
    use Doctrine\ORM\Mapping\ManyToOne;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\ORM\Mapping as ORM;
     
    /**
     * @ORM\Entity(repositoryClass="XXXBundle\Repository\CategoryRepository")
     * @ORM\Table(name="category") 
     */
    class Category
    {
    	/** 
    	 * @ORM\Id 
    	 * @ORM\Column(name="id", type="integer") 
    	 * @ORM\GeneratedValue(strategy="AUTO") 
    	 */
        private $id;
     
        /** 
         * @ORM\Column(type="string", length=100) 
         */
        private $name;
     
        /**
         * @ORM\OneToMany(targetEntity="Activity", mappedBy="category")
         */
        private $activity;
     
        /**
         * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
         */
        private $children;
     
        /**
         * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
         * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
         */
        private $parent;
     
     
        public function __construct()
        {
            $this->activity = new \Doctrine\Common\Collections\ArrayCollection();
        	$this->children = new \Doctrine\Common\Collections\ArrayCollection();
        }
     
        /**
         * Get id
         *
         * @return integer 
         */
        public function getId()
        {
            return $this->id;
        }
     
        /**
         * Set name
         *
         * @param string $name
         */
        public function setName($name)
        {
            $this->name = $name;
        }
     
        /**
         * Get name
         *
         * @return string 
         */
        public function getName()
        {
            return $this->name;
        }
     
        /**
         * Add activity
         *
         * @param XXX\Entity\Activity $activity
         */
        public function addActivity(\XXX\Entity\Activity $activity)
        {
            $this->activity[] = $activity;
        }
     
        /**
         * Get activity
         *
         * @return Doctrine\Common\Collections\Collection 
         */
        public function getActivity()
        {
            return $this->activity;
        }
     
        /**
         * Add children
         *
         * @param XXX\Entity\Category $children
         */
        public function addCategory(\XXX\Entity\Category $children)
        {
            $this->children[] = $children;
        }
     
        /**
         * Get children
         *
         * @return Doctrine\Common\Collections\Collection 
         */
        public function getChildren()
        {
            return $this->children;
        }
     
        /**
         * Set parent
         *
         * @param XXX\Entity\Category $parent
         */
        public function setParent(\XXX\Entity\Category $parent)
        {
            $this->parent = $parent;
        }
     
        /**
         * Get parent
         *
         * @return XXX\Entity\Category 
         */
        public function getParent()
        {
            return $this->parent;
        }
     
    }
    Mon but est de faire un formulaire permettant de rajouter une catégorie. Ce formulaire aura 2 champs:
    - 1 champ texte pour entrer le nom de la catégorie nouvellement créée
    - 1 select qui liste les catégories existantes, ainsi qu'une valeur "aucune catégorie" dans le cas où je souhaite créer une catégorie principale.

    Je bloque sur la création de ce select, je ne sais pas si je dois utiliser un formBuilder avec un champ de type "choice" ou un champ de type "entity".

    Voici le code de CategoryType ou j'ai mis ma méthode FormBuilder:

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <?php
    namespace XXX\Form\Type;
     
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilder;
    use XXX\Entity\Category; 
     
     
    class CategoryType extends AbstractType
    {
    	public function buildForm(FormBuilder $builder, array $options)
        {
     
            $builder->add('name', null, array('label' => 'Nom'));
     
    //          $builder->add('name','choice', array(
    //         		'label' => 'Categorie Parent',
    // 				'choices' => array('m' => 'Male', 'f' => 'Female')
    //         		)); 
     
    //         $builder->add('name', 'entity', array(
    //         		'class' => 'XXXBundle:Category',
    //         		'query_builder' => function(EntityRepository $er) {
    //         		return $er->createQueryBuilder('c')
    //         		->orderBy('c.name', 'ASC');
    //         },
    //         ));
     
    //                 $builder->add('name', 'entity', array(
    //                 		'class' => 'XXXBundle:Category',
    //                 		));
        }
     
    	public function setDefaultOptions(OptionsResolverInterface $resolver)
    	{
    		$resolver->setDefaults(array(
    				'data_class' => 'XXX\Entity\Category',
    		));
    	}
     
    	public function getName()
    	{
    		return 'category';
    	}
    }
    Je vous avoue que je suis un peu paumé sur l'ajout des champs de type choice et entity....

    J'ai aussi créé une classe CategoryRepository car apparemment c'est util si j'utilise un champ de type entité sur mon formulaire:

    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
    <?php
     
    namespace XXX\Repository;
     
    use Doctrine\ORM\EntityRepository;
     
    /**
     * CategoryRepository
     *
     * This class was generated by the Doctrine ORM. Add your own custom
     * repository methods below.
     */
    class CategoryRepository extends EntityRepository
    {
    	public function findAllOrderedByName()
    	{
    		return $this->getEntityManager()
    		->createQuery('SELECT c FROM XXXBundle:Category c ORDER BY c.name ASC')
    		->getResult();
    	}
    }
    Si vous avez des conseils, des infos avisées pour que je puisse faire ce simple formulaire de la manière la plus simple possible, je suis tout ouïe

  2. #2
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Essaye un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     ->add('parent','entity',array(
                'class'=>'XXXBundle:Category',
                'property'=>'name',
                'label'=>'Choix de categorie parent',
    )
    Par contre n'ayant jamais utilisé de relation 'self-referenced' je ne t'assure pas de l'exactitude de ma solution mais ça peut déjà te donner une piste.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    Ca a presque l'air de marcher. En tout cas maintenant j'ai bien mon champ select qui fonctionne et qui me ramène mes catégories.

    Le hic, c'est que je voudrai que ça ne me ramène que les catégories principales, c'est à dire les catégories dont le parent_id est null, hors là ça me ramène toutes les catégories, que ce parent_id soit null ou pas.

    Et puis je n'ai pas trop compris à quoi doit correspondre la première valeur qu'on met dans la méthode add ('parent' ici en l'occurence), si je change parent par 'id', le code source du formulaire reste le même par exemple.

    Merci en tout cas

  4. #4
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Alors pour ce que tu veux je pense que c'est plutôt un truc de ce genre la qu'il faut essayer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    ->add('parent','entity',array(
                'class'=>'XXXBundle:Category',
                'property'=>'name',
                'label'=>'Choix de categorie parent',
                'query_builder' => function(CategoryRepository $er) {
                    return $er->createQueryBuilder('c')
                        ->where('c.parent != null')
                        ->orderBy('c.name', 'ASC')
                }
            ))
    Et pour la première valeur de la méthode add il s'agit du nom de l'attribut de ton entité que tu souhaite remplir avec ce champ de formulaire.
    Dans ton cas il s'agit de l'attribut $parent que tu utilise pour faire ta jointure.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    Merci, c'etait presque ça

    Il y a juste la requete qui n'est pas totalement juste, je dois remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ->where('c.parent != null')
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ->where('c.parent is null')


    Par contre, j'ai vu que les bonnes pratiques voulaient que l'on crée des fonctions dans le repository pour recupérer les données, du coup j'ai créé la méthode suivante dans CategoryRepository:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		public static function getMainCategories()
    	{
    		return $this->getEntityManager()
    		->createQuery('SELECT c FROM XXXBundle:Category c WHERE c.parent_id is null ORDER BY c.name ASC')
    		->getResult();
    	}
    J'aimerai l'utiliser dans ma form du coup à la place du Query Builder, du coup j'ai fait ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    'query_builder' => CategoryRepository::getMainCategories()
    Mais je doute que cette façon de faire est propre...

    Et de toutes façons, ça ne fonctionne pas, j'ai l'erreur suivante:

    Fatal error: Using $this when not in object context in C:\xampp\htdocs\Symfony\XXX\src\XXXBundle\Repository\CategoryRepository.php on line 24
    Merci de ton aide, ca va me permettre d'appréhender un peu mieux les formulaires par Symfony (et si d'ailleurs tu as un bouquin ou un site a recommander sur Symfony hormis le site officiel avec le book, je suis preneur )

  6. #6
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Fait plutôt ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    'query_builder' => function(CategoryRepository $cr){
                    return $cr->getMainCategories();
                }
    Et enlève static sur ta fonction dans le repo

    Et pour ton erreur fait voir ton repository en entier

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    Merci de m'accorder ton temps!

    Voici le code du repository:
    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
    23
    24
    25
    26
    27
    28
    29
     
    <?php
     
    namespace XXXBundle\Repository;
     
    use Doctrine\ORM\EntityRepository;
     
    /**
     * CategoryRepository
     *
     * This class was generated by the Doctrine ORM. Add your own custom
     * repository methods below.
     */
    class CategoryRepository extends EntityRepository
    {
    	public function findAllOrderedByName()
    	{
    		return $this->getEntityManager()
    		->createQuery('SELECT c FROM XXXBundle:Category c ORDER BY c.name ASC')
    		->getResult();
    	}
     
    	public function getMainCategories()
    	{
    		return $this->getEntityManager()
    		->createQuery('SELECT c FROM XXXBundle:Category c WHERE c.parent_id is null ORDER BY c.name ASC')
    		->getResult();
    	}
    }
    En l'état, avec la modif préconisée apportée, si je relance ma page j'ai l'erreur suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [Semantical Error] line 0, col 57 near 'parent_id is': Error: Class XXXBundle\Entity\Category has no field or association named parent_id
    Du coup dans mon entité Category.php, j'ai remplacé mon champ $parent en $parent_id, et par la même occasion j'ai mis à jour l'annotation de children:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
        /**
         * @ORM\OneToMany(targetEntity="Category", mappedBy="parent_id")
         */
        private $children;
     
        /**
         * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
         * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
         */
        private $parent_id;
    Cependant, j'ai encore une erreur car du coup l'objet attendu doit être un Query Builder et je renvoie un Array avec ma méthode.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Expected argument of type "Doctrine\ORM\QueryBuilder", "array" given
    J'ai regardé de nouveau ma méthode getMainCategories dans mon CategoryRepository, mais je ne sais pas trop en terme de réusabilité si c'est mieux que je renvoie un objet de type array comme c'est le cas actuellement (et dans ce cas, quid de l'utilisation de l'array dans mon objet entity du form builder) ou si c'est mieux que je renvoie un query builder avec ma fonction.

    Saurais du me conseiller de la meilleure marche a suivre?

  8. #8
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Du coup dans mon entité Category.php, j'ai remplacé mon champ $parent en $parent_id, et par la même occasion j'ai mis à jour l'annotation de children
    Perso moi j'aurai laissé $parent et j'aurai changé la requête dans le repository.

    J'ai regardé de nouveau ma méthode getMainCategories dans mon CategoryRepository, mais je ne sais pas trop en terme de réusabilité si c'est mieux que je renvoie un objet de type array comme c'est le cas actuellement (et dans ce cas, quid de l'utilisation de l'array dans mon objet entity du form builder) ou si c'est mieux que je renvoie un query builder avec ma fonction.
    Il me semble que tu n'as pas le choix tu doit retourner un query builder pour les champs entity.
    En terme de réusabilité tu peux toujours appeler la méthode getMainCategories et faire un ->getResult() ensuite

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    Perso moi j'aurai laissé $parent et j'aurai changé la requête dans le repository.
    Je viens de réaliser que ma requête ne se base pas sur les noms des champs en base de donnée (parent_id du joinColumn) mais plutôt sur le nom du champ de l'objet (en l'occurence parent), j'ai juste?

    J'ai voulu faire ce que tu dis, à savoir faire un getResult() après mais du coup l'objet que je renvoie est du type Query, et non du type QueryBuilder. Et avec l'auto complétion proposée par Eclipse, je ne vois pas de méthode getResults pour les objets de type QueryBuilder, comment faire alors pour utiliser ce type de fonction dans un autre contexte que celui de mon problème afin de récupérer une liste de résultats?

    EDIT:

    j'ai retouché ma fonction getMainCategories:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		return $this->getEntityManager()
    					->createQueryBuilder()
    					->select('c')
    					->from('XXXBundle:Category','c')
    					->where('c.parent is null')
    					->orderBy('c.name','ASC');
    Et ce coup ci ca marche

    Mais du coup comment faire si je veux utiliser mon queryBuilder pour récupérer un array de résultats?

  10. #10
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Je viens de réaliser que ma requête ne se base pas sur les noms des champs en base de donnée (parent_id du joinColumn) mais plutôt sur le nom du champ de l'objet (en l'occurence parent), j'ai juste?
    Tout juste. C'est vrai que ce n'est évident au début d'arriver à dissocier l'objet de la base. Le truc c'est d'oublier qu'il y a une base. A part lors de la création de tes entités tu n'as pas à penser à la base tout est dans les objets.

    Mais du coup comment faire si je veux utiliser mon queryBuilder pour récupérer un array de résultats?
    Tu fait ->getQuery()->getResult(); après ton queryBuilder.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 90
    Points : 54
    Points
    54
    Par défaut
    Ok, merci pour toutes ces informations et désolé pour ces questions simplistes, au moins ça m'a aidé à mieux comprendre certains points

    Problème résolu, un grand merci l'ami!

    PS: si jamais tu as un livre carrément à me recommander pour avoir une formation très complète sur le sujet, je suis preneur

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [2.x] [Form] Entity Field non préchargé
    Par Seb33300 dans le forum Symfony
    Réponses: 9
    Dernier message: 15/01/2013, 18h08
  2. [2.x] Formulaire et Entity Field
    Par Sports dans le forum Symfony
    Réponses: 0
    Dernier message: 06/06/2012, 18h38
  3. Réponses: 7
    Dernier message: 19/06/2011, 05h56
  4. [CSS][formulaire] connaitre le type d'un champ input
    Par psychomatt dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 22/09/2005, 12h13
  5. Formulaire, champs de type file, value
    Par Space Cowboy dans le forum Langage
    Réponses: 1
    Dernier message: 12/09/2005, 08h29

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