Search code examples
symfonyvariablesobjectattributestwig

Symfony Twig : get Object property with a variable property


Symfony 3.0 :

In my project, I have many entities which contain more than 50 fields, so for the twig which shows every entity, I decided to automate the display of the 50 fields by a simple loop.

First problem: how to get entity's all fields names, I resolved this by creating a custom twig filter:

<?php
// src/HomeBundle/Twig/HomeExtension.php
namespace HomeBundle\Twig;

class HomeExtension extends \Twig_Extension
{
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('object_keys', array($this, 'getObjectKeys')),
        );
    }

    public function getObjectKeys($object)
    {
        //Instantiate the reflection object
        $reflector = new \ReflectionClass( get_class($object) );

        //Now get all the properties from class A in to $properties array
        $properties = $reflector->getProperties();
        $result=array();
        foreach ($properties as $property)
            $result[] = $property->getName();

        return $result;
    }

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

?>

The second problem which generates the error right now is: how to access object properties within a loop:

{% for property in article|object_keys%}
    <tr>
        <th>
            {{property|capitalize}}
            {# that's work clean #}
        </th>
        <td>
            {{ attribute(article,property) }}
            {# that's generate the error #}
        </td>
    </tr>
{% endfor %}

The error :

An exception has been thrown during the rendering of a template ("Notice: Array to string conversion"). 500 Internal Server Error - Twig_Error_Runtime

Finally, the error is fixed on the getObjectKeys method of the filter,

so when it returns an array that I create manually it works:

return array("reference","libelle");

But, when I send an array created within a loop => Error.

I dumped the two arrays in the twig, they were equivalents, but the second still generating an error.


Solution

  • Most likely one of your properties is returning an array rather than a simple string, integer, .... A solution here could be to store the value in a variable and check whether the stored value is an array. Depending on that check do something with the value or otherwise just output the variable

    {% for property in article|object_keys%}
    <tr>
        <th>
            {{property|capitalize}}
        </th>
        <td> 
            {% set value = attribute(article,property) %}
            {% if value is iterable %}{# test if value is an array #}
                {{ value | join(', ') }}
            {% else %}
                {{ value }}
            {% endif %}
        </td>
    </tr>                   
    {% endfor%}