Можно ли декодировать JSON в веточке? Googling, похоже, ничего не дает об этом. Не имеет смысла декодирование JSON в Twig?
Я пытаюсь получить доступ к 2 свойствам объекта в типе поля сущности Symfony2 ( Тип поля Entity ).
После того, как вы встретите 2 предыдущих вопроса SO ( тип поля объекта Symfony2 альтернативы «property» или «__toString ()»? И Symfony 2 создайте поле формы сущности с 2 свойствами ), который предложил добавить дополнительный метод для объекта для извлечения настраиваемой строки а не атрибут сущности, я подумал о (и сделал), возвращая строку JSON, представляющую экземпляр объекта.
Где-то в классе сущностей:
/** * Return a JSON string representing this class. */ public function getJson() { return json_encode(get_object_vars($this)); }
И в форме (что-то вроде):
$builder->add('categories', 'entity', array ( ... 'property' => 'json', ... ));
Впоследствии я надеялся на json_decode
в Twig …
{% for category in form.categories %} {# json_decode() part is imaginary #} {% set obj = category.vars.label|json_decode() %} {% endfor %}
Это легко, если вы расширяете веточку .
Во-первых, создайте класс, который будет содержать расширение:
<?php namespace Acme\DemoBundle\Twig\Extension; use Symfony\Component\DependencyInjection\ContainerInterface; use \Twig_Extension; class VarsExtension extends Twig_Extension { protected $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function getName() { return 'some.extension'; } public function getFilters() { return array( 'json_decode' => new \Twig_Filter_Method($this, 'jsonDecode'), ); } public function jsonDecode($str) { return json_decode($str); } }
Затем зарегистрируйте этот класс в файле Services.xml:
<service id="some_id" class="Acme\DemoBundle\Twig\Extension\VarsExtension"> <tag name="twig.extension" /> <argument type="service" id="service_container" /> </service>
Затем используйте его на своих шаблонах ветви:
{% set obj = form_label(category) | json_decode %}
Я придумал способ добраться до своего JSON, и я подумал, что поделюсь с ним здесь, если он будет полезен кому-то другому.
поэтому в моем случае у меня есть, возможно, 10 записей (макетов), возвращаемых из mysql db, и каждая строка имеет поле, называемое свойствами, которое является json-строкой. Итак, я могу легко вытащить записи и отправить их в шаблон следующим образом:
echo $twig->render('template.html.twig', array( "layouts" => $layouts, ));
До сих пор так хорошо, но когда я делаю свой {% для макета в макетах%} в ветке, нет способа добраться до элементов поля свойств, поскольку они все еще являются json-строкой.
Таким образом, перед тем, как передать $ layouts шаблону ветки, я сделал следующее:
foreach($layouts as $i => $v) { $layouts[$i]->decoded = json_decode($v->getProperties()); }
сделав это, Ive создал переменную «на лету» в моем объекте под названием «декодированный», который содержит json-декодированный объект.
Итак, теперь в моем шаблоне я могу получить доступ к своим json-элементам {{layout.decoded.whatever}}
Это может быть немного взломанным, а не всякой идеей хорошего решения. Я хорошо работаю для меня, очень немного накладных расходов и означает, что мне не нужно путаться с расширением ветки, поскольку я делаю работу, прежде чем она попадет в шаблон.
Альтернатива всем вышеперечисленным.
И я не знаю, является ли это оптимальным решением, но оно работает .
1) Создайте вспомогательную функцию и зарегистрируйте ее функцию.
<?php function twig_json_decode($json) { return json_decode($json, true); }
2) Используйте эту функцию в своем файле twig .
{% set res = twig_json_decode(json) %} # above will return an array which can be iterated {% for r is res %} {{ r }} {% endfor %}
Обновленный код для Symfony2.8 или Symfony3:
<?php namespace Acme\DemoBundle\Twig\Extension; use Symfony\Component\DependencyInjection\ContainerInterface; use \Twig_Extension; class VarsExtension extends Twig_Extension { protected $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function getName() { return 'some.extension'; } // Note: If you want to use it as {{ json_decode(var) }} instead of // {{ var|json_decode }} please use getFunctions() and // new \Twig_SimpleFunction('json_decode', 'json_decode') public function getFilters() { return [ // Note that we map php json_decode function to // extension filter of the same name new \Twig_SimpleFilter('json_decode', 'json_decode'), ]; } }
В моем случае у меня есть JsonArray в моей Entity, тогда я добавляю в свою Entity метод
<?php namespace ACME\DefaultBundle\Entity; /*...*/ public function getDecodedPath() { return json_decode($this->path); }
Это старый вопрос, но я добавляю свое решение для записи … Просто растяните Twig с помощью SimpleFunction:
// Return a string of separated values from a JSON string // Can optionally specify a separator. If none provided, ", " is used. $function = new Twig_SimpleFunction('json_to_list', function($json, $separator = ", ") { $result = ""; $array = json_decode($json, true); foreach ($array as $item) { if ($result != "") { $result .= $separator; } $result .= $item; } return $result; }); $twig->addFunction($function);
Применение:
перед вызовом рендеринга Twig установите a_json_variable в строку '["1", "2", "3", "4", "5"]'.
Шаблон Twig:
The values are: {{ json_to_list(a_json_variable) }}
Будет производить
The values are: 1, 2, 3, 4, 5
Для Symfony 3.1, как говорит официальный документ , для этой цели есть помощник: return $this->json()
:
/** * @Route("/", name="homepage") * @Method({"GET","POST"}) */ public function indexAction() { $person = new Person(); $form = $this->createForm(PersonType::class, $person,[ 'action'=>$this->generateUrl('homepage'), 'method'=>'POST' ]); $form->handleRequest($request); if($form->isSubmitted() && $form->isValid()){ return $this->json([ 'name'=>$person->getName(), 'age'=>$person->getAge() ]); } return $this->render('default/index.html.twig',['form'=>$form->createView()]); }
Результат выглядит так:
{"name":"john","age":39}