Прокрутка по свойствам объекта
Я прочитал в документации Twig, что можно перебирать ассоциативный массив следующим образом:
{% for key, value in array %}
{{key}}
{{value}}
{% endfor %}
Мне было интересно, возможно ли это для объектов типа stdClass. Я пробовал, и он не работает.
EDIT:
Я бы ожидал, что Twig будет перебирать значения свойств объекта, используя имена свойств в качестве ключей. Вместо этого блок команд, содержащийся в цикле for, вообще не выполняется.
Ответы
Ответ 1
Вы можете сначала передать объект в массив. Вы можете создать собственный фильтр, отбрасывающий ваш объект в массив. Подробнее о фильтрах можно найти здесь: http://twig.sensiolabs.org/doc/advanced.html#filters
Тогда он может выглядеть следующим образом:
{% for key, value in my_object|cast_to_array %}
Ответ 2
После загрузки TWIG добавьте этот фильтр:
$twig->addFilter( new Twig_SimpleFilter('cast_to_array', function ($stdClassObject) {
$response = array();
foreach ($stdClassObject as $key => $value) {
$response[] = array($key, $value);
}
return $response;
}));
Он назвал cast_to_array после Tadeck.:)
Я уверен, что он не работает для какого-либо объекта stdClass, но он наверняка решил мою проблему с печатью ассоциативных массивов PHP:) Используйте его следующим образом:
{% for key, value in my_object|cast_to_array %}
<td>{{ value.1 }}</td>
{% endfor %}
Боковая история
Поскольку я много раз попадал на эту страницу SO, я думаю, что уместно показать, где я использую Twig для итерации над свойствами объекта, поэтому это полезно для других людей с одинаковой проблемой:
Я пытался распечатать таблицу из источника .json, но PHP json_decode преобразует любой "ключ": "значение" в ассоциативный массив PHP, который по умолчанию не печатает Twig.
Таким образом, этот фильтр разрезает и доставляет обычный массив, который будет использоваться 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>
Ответ 3
Чтобы завершить ответ Тадека, вот как:
Если вы еще не создали или не установили расширение Twig (фильтр), вам нужно будет сначала выполнить эту инструкцию http://symfony.com/doc/2.7/cookbook/templating/twig_extension.html
1) добавьте в свой 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) добавьте в свой AppBundle/Twig/AppExtension.php
public function objectFilter($stdClassObject) {
// Just typecast it to an array
$response = (array)$stdClassObject;
return $response;
}
3) В вашей строке example.html.twig через ветку и фильтр.
{% for key, value in row|cast_to_array %}
<td id="col" class="hidden-xs">{{ value }}</td>
{% endfor %}
Готово, надеюсь, это поможет. От указателя Тадека.
Ответ 4
Я знаю, что это старый, но не
$assoc_array = json_decode(json_encode($stdClassObject), TRUE);
работает так же хорошо?
Ответ 5
Если это помогает кому-то другому. Вы можете заставить Twig перебирать свойства вашего объекта, если вы реализуете интерфейс PHP Iterator.
В моем случае у меня есть общий объект, который использует магические методы __get(), __set(), __isset() и __unset() при сохранении пар ключей в частном массиве. Это отлично работает в Twig, пока вы не захотите перебирать объект, используя что-то вроде этого
<ul>
{% for prop, value in object %}
<li>{{prop|replace({'_': ' '})|title}}</li>
{% endfor %}
</ul>
Чтобы сделать это, мне пришлось реализовать интерфейс Iterator. Затем приведенный выше код работал отлично.
Теперь из-за магии __get() имена свойств не чувствительны к регистру, поэтому каждый из них также работает.
<ul>
{% for object in arrayOfObjects %}
<li>{{ object.property }}</li>
<li>{{ object.Property }}</li>
<li>{{ object.PROPERTY }}</li>
{% endfor %}
</ul>