Декодирование JSON в Twig
Можно ли декодировать JSON в twig? Googling, похоже, ничего не дает об этом. Не имеет смысла декодирование JSON в Twig?
Я пытаюсь получить доступ к 2 свойствам сущности в типе поля сущности Symfony2 (Тип поля Entity).
После появления двух предыдущих SO-вопросов (тип поля сущности Symfony2 альтернативы "свойству" или "__ 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 %}
Ответы
Ответ 1
Это легко, если вы удлините ветку.
Сначала создайте класс, который будет содержать расширение:
<?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 %}
Ответ 2
Я придумал способ добраться до своего 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 создал переменную "на лету" в моем объекте с именем "decoded", который содержит json-декодированный объект.
Итак, теперь в моем шаблоне я могу получить доступ к своим json-элементам с помощью {{layout.decoded.whatever}}
Это может быть немного взломанным, а не всякой идеей хорошего решения. Я хорошо работаю для меня, очень немного накладных расходов и означает, что мне не нужно путаться с расширением ветки, как Im, делающей работу до того, как она попадет в шаблон.
Ответ 3
альтернативный для всех выше.
И я не знаю, является ли это оптимальным решением, но работает.
1) Создайте вспомогательную функцию и register, которая ее выполняет.
<?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 %}
Ответ 4
Обновлен код для 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'),
];
}
}
Ответ 5
В моем случае у меня есть JsonArray в моей Entity, тогда я добавляю в свой Entity метод
<?php
namespace ACME\DefaultBundle\Entity;
/*...*/
public function getDecodedPath()
{
return json_decode($this->path);
}
Ответ 6
Это старый вопрос, но я добавляю свое решение для записи... Просто растяните 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
Ответ 7
Для 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}