Bonjour,

J'ai 2 entités : Platform et Domaine qui sont liées entre elles par une relation ManytoMany :

Platform.php:

<?php

namespace US\PlatformBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Platform
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="US\PlatformBundle\Entity\PlatformRepository")
 */
class Platform
{
    public function __construct()
    {
        $this->domaines = new ArrayCollection();
    }

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=150)
     */
    private $nom;

    /**
     * @Gedmo\Slug(fields={"nom"})
     * @ORM\Column(length=150, unique=true)
     */
    private $slug;

    /**
     * @var string
     *
     * @ORM\Column(name="adresse", type="text")
     */
    private $adresse;

    /**
     * @ORM\ManyToMany(targetEntity="US\PlatformBundle\Entity\Domaine", cascade={"persist"})
     */
    private $domaines;
}

Domaine.php

<?php

namespace US\PlatformBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * Domaine
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="US\PlatformBundle\Entity\DomaineRepository")
 * @UniqueEntity("nom")
 */
class Domaine
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=255, unique=true)
     */
    private $nom;
}

La relation est visible grâce à l'attribut :

private $domaines;

dans l'entité Platform.

Une liste de domaine existe déjà en BDD :

id nom

1 Informatique

2 Mecanique

3 Biologie

Je possède un formulaire PlatformType qui permet de créer une platform, et proposant un champ select multiple avec la liste de tout les domaines existant en base.

PlatformType.php :

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('nom', 'text', array('required' => true))
        ->add('adresse', 'textarea', array('required' => true))
        ->add('domaines', 'entity', array(
            'class'    => 'USPlatformBundle:Domaine',
            'property' => 'nom',
            'multiple' => true,
            'required' => true
        ))
        ->add('enregistrer','submit')
    ;
}

Par exemple j'ai créer une platform appelé "université montpellier 2" qui possède les domaines "Informatique et Biologique".

Jusque la tout va bien.

Maintenant, j'ai une entité User qui est en relation ManytoOne avec la table Platform (un utilisateur appartient à une platform).

User.php :

/**
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @var string
 *
 * @ORM\Column(name="lastname", type="string", length=50, nullable=true)
 */
private $lastname = null;

/**
 * @var string
 *
 * @ORM\Column(name="firstname", type="string", length=50, nullable=true)
 */
private $firstname = null;

/**
 * @ORM\ManyToOne(targetEntity="US\PlatformBundle\Entity\Platform")
 * @ORM\JoinColumn(nullable=true)
 */
private $platform;

Le lien est fait par :

private $platform;

Lorsque l'utilisateur est créé, il est automatiquement associé à une platform. Exemple : l'utilisateur Romain appartient à la Platform université montpellier 2 qui pour domaine Informatique et Biologique.

Maintenant j'ai un formulaire UserType qui permet à l'utilisateur connecté (par exemple Romain) de modifier ses informations personnelles (firstname et lastname) et j'aimerai en plus permettre à l'utilisateur de choisir grâce à un champ select simple, le domaine dans lequel il étudie. Biensur vu que Romain est associé à la platform université montpellier 2, la liste déroulante du select ne doit proposé uniquement les domaines qui sont associés à la platform. Dans notre cas, la liste déroulante doit permettre à Romain de choisir entre Informatique et Biologique uniquement.

Pour ce faire, j'ai rajouté un champ : "domaine_user" dans l'entité User :

/**
 * @var string
 *
 * @ORM\Column(name="domaine_user", type="string", length=255, unique=true)
 */
private $domaine_user;

UserType.php :

$builder
    ->add('lastname','text', array('required' => false))
    ->add('firstname', 'text', array('required' => false))
    ->add('domaine_user', 'choice', array(
        'choices'  => array('informatique' => 'Informatique', 'biologie' => 'Biologie'),
        'required' => false,
        'multiple' => false,
        'empty_value' => '-- Domaine d\'étude --'
    ))

Comme vous pouvez le voir ci-dessus, j'ai mis les valeurs du select en dur dans le code.

Comment faire pour les récupérer de la BDD ?

J'ai vu qu'il était possible d'utiliser QueryBuilder sur le champs de sélection :

->add('domaine_user', 'entity', array(
    'class'    => 'USPlatformBundle:Platform',
    'property' => 'domaines',
    'multiple' => false,
    'required' => false,
    'query_builder' => function (\US\PlatformBundle\Entity\PlatformRepository  $er) {
       return $er->createQueryBuilder('p');

Mais je n'y arrive pas, j'ai essayé plusieurs façon avec le quiry_builder mais sans succés. Je n'arrive pas à affiché "Informatique et Biologie" dans mon select

Ai-je un problème de conception ?

Est-ce bien avec le query builder que je vais pouvoir résoudre mon problème ? Comment ?

Merci de votre aide

1 réponse


A partir du moment ou tu dois changer la liste en fonction de la BDD, il faut absoluement passer par le query builder. La requete doit retourner les domaines pour lesquels l'utilisateur X est associé. Tu peux aussi passer un tableau a ta classe de formulaire et l'injecter dans le champs. Dans ce cas le tableau devra envoir en key l'id du domaine et en value le libelle en fonction de ta requête.

Le propriété "domaine_user" doit être de type many to one est non de type string. Il faudra juste reteindre les données aux domaines de la plateforme à laquelle il est inscrit.

Le form type "domaine_user" ne peut être plateforme car tu choisis d'agir sur les domaines.

Voici une des solutions possibles (au niveau du raisonnement):

Tu devras passer l'id de la plateforme au form type via le consctructeur de ta classe.

->add('domaine_user', 'entity', array(
    'class'    => 'USPlatformBundle:Domaine',
    'property' => 'name',
    'multiple' => false,
    'required' => false,
    'query_builder' => function (\US\PlatformBundle\Entity\DomaineRepository  $er) {
       return $er->createQueryBuilder('d')
        ->where('d.plateforme = :plateFormeId')
        ->setParameters(array('plateFormeId' => $this->plateformeId));