web-dev-qa-db-fra.com

Twig itère sur les propriétés des objets

J'ai lu dans la documentation Twig qu'il est possible d'itérer sur un tableau associatif de la manière suivante:

{% for key, value in array %}  
 {{key}}  
 {{value}}  
{% endfor %}  

Je me demandais si cela était également possible pour les objets de type stdClass.

Je m'attendais à ce que Twig répète les valeurs de propriété de l'objet en prenant les noms de propriété comme clés. Au lieu de cela, le bloc d'instructions contenu dans la boucle for n'est pas exécuté du tout.

23
Bogdan

Vous pouvez d'abord convertir l'objet en tableau. Vous pouvez créer votre propre filtre en convertissant votre objet en tableau. Plus d'informations sur les filtres sont disponibles ici: http://twig.sensiolabs.org/doc/advanced.html#filters

Cela pourrait alors ressembler à ça:

{% for key, value in my_object|cast_to_array %}
22
Tadeck

Après avoir chargé TWIG, ajoutez ce filtre:

$twig->addFilter( new Twig_SimpleFilter('cast_to_array', function ($stdClassObject) {
    $response = array();
    foreach ($stdClassObject as $key => $value) {
        $response[] = array($key, $value);
    }
    return $response;
}));

Il est nommé cast_to_array d'après la suggestion de Tadeck . :) Je suis sûr que cela ne fonctionne pour aucun type d'objet stdClass, mais cela a résolu mon problème d'impression PHP associatif tableaux :) Utilisez-le comme suit:

{% for key, value in my_object|cast_to_array %}
    <td>{{ value.1 }}</td>
{% endfor %}

Histoire parallèle

Depuis que je suis entré dans cette page SO beaucoup, je pense qu'il est pertinent de montrer où j'utilise Twig for itération sur les propriétés des objets, donc c'est utile pour d'autres personnes ayant le même problème: j'essayais d'imprimer une table à partir d'une source .json, mais json_decode de PHP transforme tout "clé": "valeur" dans un PHP tableau associatif, qui Twig ne s'imprime pas par défaut. Donc ce filtre coupe et délivre un tableau régulier à utiliser par Twig.

source.json

{
    "user": {
        "family": {
            "table": [{
                "First_Name": "John",
                "Last_Name": "Foo",
                "Age": 25,
                "Role": "Brother"
            }, {
                "First_Name": "Mary",
                "Last_Name": "Bar",
                "Age": 14,
                "Role": "Sister"
            }, {
                "First_Name": "Joe",
                "Last_Name": "Baz",
                "Age": 33,
                "Role": "Uncle"
            }]
        }
    }
}

Twig

<table>
  <thead>
    <tr> {# get table headers from the table row #}
      {% for row in user.family.table.0|cast_to_array %}
        <th>{{ row.0 | replace({'_': ' '}) }}</th>
      {% endfor %}
    </tr>
  </thead>
  <tbody>
    {% for row in user.family.table %}
      <tr>
      {% for key, value in row|cast_to_array %}
        <td>{{ value.1 }}</td>
      {% endfor %}
      </tr>
    {% endfor %}
  </tbody>
</table>
8
roberto.cr

Pour compléter la réponse de Tadeck, voici comment:

Si vous n'avez jamais créé ou configuré une extension Twig (filtre), vous devrez d'abord suivre ces instructions http://symfony.com/doc/2.7/cookbook/ templating/twig_extension.html

1) ajoutez à votre AppBundle/Twig/AppExtension.php ('cast_to_array')

public function getFilters()
{
    return array(
        new \Twig_SimpleFilter('md2html', array($this, 'markdownToHtml'), array('is_safe' => array('html'))),
        new \Twig_SimpleFilter('price', array($this, 'priceFilter')),
        new \Twig_SimpleFilter('cast_to_array', array($this, 'objectFilter')),
    );
}

2) Ajoutez à votre AppBundle/Twig/AppExtension.php

public function objectFilter($stdClassObject) {
    // Just typecast it to an array
    $response = (array)$stdClassObject;

    return $response;
}

3) Dans votre boucle example.html.twig avec twig et le filtre.

{% for key, value in row|cast_to_array %}
       <td id="col" class="hidden-xs">{{ value }}</td>
{% endfor %}

C'est fait, j'espère que ça aide. Du pointeur de Tadeck.

6
Dung

Au cas où cela aiderait quelqu'un d'autre. Vous pouvez avoir Twig itérer les propriétés de votre objet à condition que vous implémentiez l'interface Iterator de PHP.

Dans mon cas, j'ai un objet générique qui utilise les méthodes magiques __get (), __set (), __isset () et __unset () tout en stockant des paires de valeurs clés dans un tableau privé. Cela fonctionne très bien dans Twig jusqu'à ce que vous vouliez itérer sur l'objet en utilisant quelque chose comme ça

<ul>
{% for prop, value in object %}
    <li>{{prop|replace({'_': ' '})|title}}</li>
{% endfor %}
</ul>

Pour que cela fonctionne, j'ai dû implémenter l'interface Iterator. Ensuite, le code ci-dessus a parfaitement fonctionné.

Maintenant, en raison de la magie __get (), les noms de propriété ne sont pas sensibles à la casse, donc chacun de ces travaux fonctionne également.

<ul>
{% for object in arrayOfObjects %}
    <li>{{ object.property }}</li>
    <li>{{ object.Property }}</li>
    <li>{{ object.PROPERTY }}</li>
{% endfor %}
</ul>
2
kbull

Je sais que c'est vieux mais non

$assoc_array = json_decode(json_encode($stdClassObject), TRUE);

fonctionne aussi bien?

2
Guest9000000