Lex Hartman
Lex Hartman

Reputation: 178

Filter collection in Symfony formtype

Summary

I have three entities: User, Organisation and OrganistionUser.

I created an Organisation form with an embedded collection of OrganisationUsers. This is working. What i can't get to work is that only Users without an assocciation (to an organisation) are 'queried' and show up in the selectbox in the OrganisationForm.

Details

Entitie 1: Organisation

class Organisation
{

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

    /**
     *
     * @ORM\Column(type="string", nullable=true)
     */
    protected $name;


    /**
     * @ORM\OneToMany(targetEntity="OrganisationUser", mappedBy="organisation_id", cascade={"persist", "remove"}, orphanRemoval=true)
     *
     * @Expose
     */
    private $users;

Entitie 2: User (I extended the FOSUserBundle)

<?php


/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{

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


    /**
     * @var string
     */
    protected $username;

    /**
     * @var \Doctrine\Common\Collections\ArrayCollection
     * @ORM\OneToMany(targetEntity="OrganisationUser", mappedBy="user_id", cascade={"ALL"}, orphanRemoval=true)
     */
    protected $organisationusers;

I have succesfully embedded a collection of forms. In my 'create-new-organisation-form' i can add many users, and they are persisted to the database.

They are persisted in the OrganisationUser table (because i only want to associate EXISTING users to an organisation).

The OrganisationUser entity (so actually i have three entities) looks as:

Entitie 3: OrganisationUser

<?php


class OrganisationUser
{

    protected $id;


    /**
     * @var ProjectId
     * @ORM\ManyToOne(targetEntity="Organisation", inversedBy="organisationusers")
     * @ORM\JoinColumn(name="organisation_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $organisation_id;


    /**
     * @var ProjectId
     * @ORM\ManyToOne(targetEntity="User", inversedBy="organisationusers")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $user_id;

NOW, in my form (OrganisionType) i embedded a collection of OrganisationUser. But i want to manipulate the data (i do not want to show all users. Only the user that are NOT associated to an organisation). How can i achieve this. I already looked here and here but it's no solution for this question so i created a new question.

The OrganistionType:

<?php

class OrganisationType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {


        $builder
            ->add('name')
            ->add('address')
            ->add('postal')
            ->add('city')
            ->add('phone')
            ->add('email')
            ->add('role');

        $builder->add('users', 'collection', array(
            'entry_type' => new OrganisationUserType(),
            'allow_add' => true,
            'allow_delete' => true,
            'by_reference' => false,
            'required' => false,
        ));


    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Organisation',
        ));
    }
}

And the OrganisationUserType:

<?php

class OrganisationUserType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->add('user_id', null ,array(
                'label' => 'User'
            ))
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\OrganisationUser'
        ));
    }

}

The controller

<?php

/**
 * Organisation controller.
 *
 * @Route("/organisation")
 */
class OrganisationController extends Controller
{    
    /**
     * Creates a new Organisation entity.
     *
     * @Route("/new", name="organisation_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request)
    {
        $organisation = new Organisation();
        $form = $this->createForm('AppBundle\Form\OrganisationType', $organisation);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($organisation);
            $em->flush();

            return $this->redirectToRoute('organisation_show', array('id' => $organisation->getId()));
        }

        return $this->render('organisation/new.html.twig', array(
            'organisation' => $organisation,
            'form' => $form->createView(),
        ));
    }

This is how it looks like when its rendered: enter image description here And, let's say if testuser3 is already associated with an organisation i dont want him to show up in the dropdown :)

Upvotes: 2

Views: 2323

Answers (1)

Lex Hartman
Lex Hartman

Reputation: 178

Ok, i found it. In my OrganisationType i use the OrganisationUserType to embed the collection of users. So in the OrganisationUserType i had to query for the result: Off course this is not the right query but i know now where to manipulate the data. Now i can go and search for the right query :)

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Doctrine\ORM\EntityRepository;

class OrganisationUserType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->add('user_id', 'entity', array(
                'class' => 'AppBundle:User',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('u')
                        ->where('u.id > :id')
                        ->setParameter('id', '1')
                        ->orderBy('u.username', 'ASC');
                },
                'choice_label' => 'username',
                'required' => false,
            ));
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\OrganisationUser',
        ));
    }

}

Upvotes: 1

Related Questions