Search code examples
symfonyscaffolding

How do you define the getter to use in a CRUD form besides defining __toString()?


If you've used Symfony2's generators to create CRUD forms from database entities, you may wind with an error like this on the "create new record" screen:

StringCastException: A "__toString()" method was not found on the objects of type
"ScrumBoard\ServiceBundle\Entity\Users" passed to the choice field. To read a
custom getter instead, set the option "property" to the desired property path.

If I'm reading this correctly, the problem is that it needs to display a dropdown list of users for the record I'm creating, but it doesn't know how to turn a "User" entity into a string.

Defining the __toString() method on my Users entity class fixes the problem. However, I can see right from the text of the error message that there is an alternative: read a customer getter instead, which is accomplished by "[setting] the option "property" to the desired property path."

This sounds like some kind of annotation. But in my searching, I can't figure out what that is. Because I want to have a thorough understanding of Symfony2--can someone help me out?

Thanks!


Solution

  • When creating an entity ( superclass of choice ) field type in a form. You need to specify which property shall be used for the labels/values otherwise the __toString() method of the underlying object will be used.

    $builder->add('users', 'entity', array(
        'class' => 'AcmeHelloBundle:User',
        'property' => 'username',
    ));
    

    Read more about it in the Form Type Reference for entity field Type.

    Additional Info

    A __toString() related error generally often comes from twig when generating a route in a template aswell. if outputting an object an object in twig with {{ object }} ... twig will call the object'S __toString method. This "trick" is used by the crud generated templates with SensioGeneratorBundle.

     {{ path('article_show', {'id': article}) }}
    

    with the route being something like this:

    article_show:
       pattern:  /article/{id}
       defaults: { _controller: AcmeArticleBundle:Article:show }
    

    If you have the __toString method in your Article entity set to something like ...

     public function __toString()
     {
         return $this->id;
     }
    

    ... you dont't need to type

    {{ path('article_show', {'id': article.id) }}
    

    Generally Twig will automatically output Article::getId() if you use

    {{ article.id }}
    

    Hope this clarifies your findings.