1

I want to create a form select field which looks like this:

<select>
<option value="product.product_id">product_details.detail_name</option>
etc...
</select>

The value is not the problem, the problem is with the label.

I have a product entity and a productDetails entity which contains translated data about a product.

So, in my form type class, in the buildForm method, I have this:

    $builder->add('product', 'entity', array(
        'class' => 'MyBundle:Product',
        'property' => 'details.detail_name',
        'query_builder' => function(EntityRepository $er) {
            return $er->createQueryBuilder('p')
                ->select('p, pd')
                ->join('p.details', 'pd')
                ->where('pd.language_id = :lang')
                ->setParameter('lang', 'en');
        }));

I want the property to be the details.detail_name.

I tried different values for this property value. Like 'details.detail_name', 'pd.detail_name' and 'p.details.detail_name'.

But it seems to be impossible to get the property to display the detail name.

When I use to above mentioned code, I get this error:

Neither property "detail_name" nor method "getDetailName()" nor method "isDetailName()" exists in class "Doctrine\ORM\PersistentCollection"

This getDetailName() method does exist in the ProductDetails entity, and I have checked the entities and they all seem to be okay. Also, they work just fine when I use these entities outside the form.

I also tried to execute the resulting query directly on my database, and it gives me the expected results. The detail_name are in the right language.

So, can somebody help me on how to make the select choice list I want, with a joined query?

2 Answers 2

2

I finally managed to get this working. Below, I'm showing how I'm doing this, in case someone else has the same problem.

I am now using a custom form type.

And in the setDefaultOptions, I am calling a repository method, which returns an array with "product_id" => "detail_name".

class ProductChoiceType extends AbstractType
{
    private $repository;

    public function __construct(EntityRepository $repository)
    {
        $this->repository = $repository;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                'choices' => $this->repository->findAllProductsForForm('nl', true)
            ));
    }

    public function getParent()
    {
        return 'choice';
    }

    public function getName()
    {
        return 'product_choice';
    }
}

In the $this->repository->findAllProductsForForm method, I am using a query and a foreach loop to make the array suitable for the choice list.

Then, I had to register the repository and this type in my services.xml file:

<service id="mybundle.repository.product"
         factory-service="doctrine.orm.default_entity_manager"
         factory-method="getRepository"
         class="MyBundle\Repository\ProductRepository" >
    <argument>MyBundle:Product</argument> <!-- not sure why I need this, but it wouldn't work without it -->
</service>

<service id="mybundle.xxx.form.product_choice_type" class="Mybundle\Form\Type\ProductChoiceType">
    <argument type="service" id="mybundle.repository.product" />
    <tag name="form.type" alias="product_choice" />
</service>

And then, in the root form type (I think it's called that) I use the 'product_choice' as a form type.

I'm not sure if this the best way to do this, but at least it works.

Now I only need to figure out how to pass on the current language of the user on to the repository, but that's a problem for later.

Sign up to request clarification or add additional context in comments.

Comments

1

From what I see your Method Product::getDetails returns Doctrine\ORM\PersistentCollection not `ProductDetails' entity (so collection not single object). It mean that product is related with details using one-to-many/many-to-many association.

You can try to do it from product details side then:

$builder->add(
    'product',
    'entity',
    array(
        'class' => 'MyBundle:ProductDetails',
        'property' => 'detail_name',
        'query_builder' => function(EntityRepository $er) {
            return $er->createQueryBuilder('pd')
                ->select('pd, p')
                ->join('pd.product', 'p')
                ->where('pd.language_id = :lang')
                ->setParameter('lang', 'en');
         }
    )

);

1 Comment

I tried this piece of code, and it worked. But, the value of the select is now the id of the product detail. It should be the product_id.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.