Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display a Many to One Relation in a form dropdown in Symfony2?

I have a a form when I need to display the OneToMany relation between let's say a car and its brand.

When I click on the dropdown for now, I can only see the car name. since it is automatically created from the car entity.

What I'd like to see in my dropdown is NameOfTheCar - NameOfTheBrand. For every choice

I have CarType with a fild like :

$builder->add('cars', 'choice', array(
        'choices'   => array(
            'Test' => 'Example',
        ),
        'required'  => true,
    ));

how can I do that ?

EDIT: I have followed Hugo advices.

Now I got

$builder->add('lake', 'entity', array(
            'class'     =>  'Pondip\KeepnetBundle\Entity\CatchReport',
            'required'  => true,
        ));

And my __toString of CatchReport is

  public function __toString()
    {
        return $this->car .' - '. $this->car->getBrand();
    }

When lake is

/**
 * @var integer
 *
 * @ORM\ManyToOne(targetEntity="Pondip\CarBundle\Entity\Car")
 * @ORM\JoinColumn(name="car_id", referencedColumnName="id")
 * @Assert\NotBlank()
 */
private $car;

and in my brand entity I have:

 /**
     * @var integer
     * @Assert\Type(type="Pondip\CarBundle\Entity\Brand")
     * 
     * @ORM\ManyToOne(targetEntity="Pondip\CarBundle\Entity\Brand")
     * @ORM\JoinColumn(name="brand_id", referencedColumnName="id")
     */
    private $brand;

And now I got an error from my toString() Function. What did I do wrong ?

Thanks

like image 218
Miles M. Avatar asked Apr 20 '13 19:04

Miles M.


1 Answers

The good way to do it is to use the 'entity' type, and to resolve the whole thing there are 2 main steps.

First step

$builder->add('cars', 'entity', array(
        'class' => 'MyBundle:Car',

        // 'property' => 'myCustom', -- The default is the __toString() (Enity file)

        'query_builder' => function(EntityRepository $er) {
            return $er->createQueryBuilder('c')
                ; // You can add anything else here or
                  // use an existing function of the repository file
    ),
    'required'  => true,
));

Normally you can set the key property to the attribute of the object you want to be used, but in your case since it's a bit more complicated you will have to override the __toString() method or make a custom attribute on the object that returns the value and set property => 'myCustom'.

Second Step:

In your entity file, which is not the repository file, but is the Cars.php file (which has the getter setters). This is for the mapping with property.

  • First: overriding the toString

    function __toString(){
        return $this->name . " - ". $this->brand;
    }
    
  • Second: making a custom method

    function getMyCustom(){
        return $this->name . " - ". $this->brand;
    }
    

Optional

For the query_builder field.
If your query to retrieve the cars is complicated, you might want to make a custom method in your car repository. In order to have the most simple as possible query in the builder. This is to retrieve the list of cars that will populate the dropdown. If you just want to retrieve all the cars, you can just specify ->findAll().


Update

The problem with your __toString seems to be that it can not call functions (I don't know why). Try something along this:

function __toString(){ // CatchReport
    return $this->car

}

function __toString(){ // Car
    return $this->name . " - " . $this->brand

}

function __toString(){ // Brand
    return $this->name

}

This way it never uses the object, and thus can not return exception on null pointer

like image 160
Hugo Dozois Avatar answered Nov 15 '22 07:11

Hugo Dozois