Bonjour à tous,

J'ai déjà posé la question sur Developpez, sur OpenClassRoom et même sur Stack Overflow, et personne ne semble pouvoir me répondre ; pourtant, ce problème est vraiment banal puisque ce que je cherche à faire est un "cas d'école".

J'ai tout simplement une entité (Module) qui possède un "OneToMany" vers une autre entité (ModuleControle). Dans ce dernier, il n'y a simplement qu'un textarea : un module possède donc X textarea.

Voici ce que j'ai fait actuellement :

ModuleType.php :

class ModuleType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('point', 'textarea', array(
                'label' => 'Point(s) à observer',
                'required' => false,
                'attr' => array(
                    'rows' => 5
                )
            ))
            ->add('controles', 'collection', array(
                'label' => false,
                'type' => new ModuleControleType(),
                'allow_add' => true,
                'allow_delete' => true,
                'by_reference' => false
            ))
        ;
    }

Et ModuleControleType.php :

class ModuleControleType extends AbstractType
{

    use Description;

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('description', 'textarea', array(
                'label' => 'Description',
                'required' => false,
                'attr' => array(
                    'rows' => $rows
                )
            ))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AdministrationBundle\Entity\ModuleControle',
            'intention' => $this->getName() . '_token'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'administration_module_controle_form';
    }
}

Jusque la, pas de soucis, c'est un cas d'école et tout fonctionne : l'ajout, la modifcation, la suppression.

Cependant, lors de la modification, Symfony 2 va chercher tout seul les éléments précédemments enregistrés ; mais je souhaite personnaliser la requête afin d'y mettre un Where.

Or et d'après la documentation, l'option "query_builder" n'est disponible que pour les types de formulaires "Entity" et moi, c'est un type "Collection".

Si quelqu'un a une idée, je bloque sur ce problème depuis 6 jours ... merci d'avance :)

4 réponses


skp
Réponse acceptée

Je pense qu'il faut que tu récupères directement tes modules avec les éléments. Par conséquent, tu ajoutes une jointure à ta requête et appliques ton « where ». De cette façon, tu n’auras qu’une seule requête et normalement ta collection devrait contenir les bons éléments.

Exemple requête :

SELECT m.*, mc.* FROM administration_module m INNER JOIN administration_module_controle mc WHERE m.date_suppression IS NULL AND mc.date_suppression IS NULL ORDER BY m.libelle ASC

Bonjour, pourrais-tu montrer ton controller ? Mais, je pense que c'est dans ton controller quand tu récupères ton "Module" que tu dois adapter ta requête.

Salut et merci de ta réponse,

Voici le controller, il est vraiment basique : il récupère le module effectivement, mais pas les éléments du module (la requête se faisant seul) :

    public function indexAction(Request $request, $page = 1)
    {
        $module_repository = $this->get('administration_module_repository');
            $modules = $module_repository->getModules();        
        return array(
            'modules' => $modules
        );
    }

A titre informatif, voici getModules() qui, lui aussi, est basique (bien que ce soit une requête faîtes à la main) :

    public function getModules()
    {
        $rsm = new ResultSetMappingBuilder($this->_em);
        $rsm->addRootEntityFromClassMetadata('AdministrationBundle:Module', 'm');
        $query = $this->_em->createNativeQuery('
            SELECT
                    m.*
            FROM
                administration_module m
            WHERE
                m.date_suppression IS NULL
            ORDER BY
                m.libelle ASC
        ', $rsm);
        return $query->getResult();
    }

Encore merci :)

Merci beaucoup de ton aide c'est parfait, ça fonctionne ! :)
Pour ceux qui se posent la question, voici la requête finale envoyée au formulaire, je précise qu'il s'agit volontairement d'une requête manuelle :

    public function getModule($module_id)
    {
        $rsm = new ResultSetMappingBuilder($this->_em);
        $rsm->addRootEntityFromClassMetadata('AdministrationBundle:Module', 'm');
        $rsm->addJoinedEntityFromClassMetadata('AdministrationBundle\Entity\ModuleControle', 'mc', 'm', 'controles', array(
            'id' => 'mc_id',
            'description' => 'mc_description',
            'date_creation' => 'mc_date_creation',
            'date_modification' => 'mc_date_modification',
            'date_suppression' => 'mc_date_suppression'
        ));
        $query = $this->_em->createNativeQuery('
            SELECT
                mc.*,
                mc.id AS mc_id,
                mc.description AS mc_description,
                mc.date_creation AS mc_date_creation,
                mc.date_modification AS mc_date_modification,
                mc.date_suppression AS mc_date_suppression,
                m.*
            FROM
                administration_module m
                INNER JOIN
                    administration_module_controle mc ON
                    m.id = mc.module_id
            WHERE
                m.date_suppression IS NULL AND
                m.id = :module_id AND
                mc.date_suppression IS NULL
        ', $rsm);
        $query->setParameter('module_id', $module_id);
        return $query->getResult();
        //return $query->getOneOrNullResult();
    }