2013-01-24 3 views
13

E 'possibile decodificare JSON in twig? Googling non sembra dare alcun risultato al riguardo. Decodificare JSON in Twig non ha senso?Decoding JSON in Twig


Sto cercando di accesso di 2 immobili entità in entità tipo di campo di uno Symfony2().

Dopo aver ricevuto 2 domande SO precedenti (Symfony2 entity field type alternatives to "property" or "__toString()"? e Symfony 2 Create a entity form field with 2 properties) che suggerivano di aggiungere un metodo aggiuntivo a un'entità per recuperare una stringa personalizzata anziché un attrib esempio.

Da qualche parte nella classe entità:

/** 
* Return a JSON string representing this class. 
*/ 
public function getJson() 
{ 
    return json_encode(get_object_vars($this)); 
} 

e nella forma (qualcosa di simile):

$builder->add('categories', 'entity', array (
... 
'property' => 'json', 
... 
)); 

In seguito, speravo di json_decode in Twig ...

{% for category in form.categories %} 
    {# json_decode() part is imaginary #} 
    {% set obj = category.vars.label|json_decode() %} 
{% endfor %} 
+0

Perché non 'json_encode()' in PHP? –

+0

Sì, faccio 'json_encode (get_object_vars ($ this))'. Il problema è la decodifica poiché deve essere in Twig e non in PHP. –

+0

Non ho familiarità con Twig/Symfony2, ma potresti decodificarlo nella tua azione e passare i risultati al tuo modello Twig? – halfer

risposta

26

Questo è facile se si extend twig.

In primo luogo, creare una classe che conterrà l'estensione:

<?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); 
    } 
} 

Poi, registrare quella classe nel file services.xml:

<service id="some_id" class="Acme\DemoBundle\Twig\Extension\VarsExtension"> 
     <tag name="twig.extension" /> 
     <argument type="service" id="service_container" /> 
</service> 

Quindi, utilizzare sui vostri modelli ramoscello:

{% set obj = form_label(category) | json_decode %} 
+0

Non dovrebbe ''json_encode'' essere'' json_decode'' all'interno di 'getFilters()'? – cheesemacfly

+0

In effetti, ho aggiornato la risposta. Saluti! – Xocoatzin

+2

Nel caso in cui tutti coloro che cercano di installazione Services.yml: 'acme_demo.twig.extension.vars_extension: classe: Acme \ DemoBundle \ Twig \ Extension \ VarsExtension argomenti: [@service_container] Tags: - {name: 'ramoscello .extension '} ' – HBK

3

mi si avvicinò con un modo di ottenere al mio JSON e ho pensato di condividerle qui nel caso in cui il suo utile a qualcun altro

quindi nel mio caso ho forse 10 record (layout) restituiti da un mysql db e ogni riga ha un campo chiamato properties che è una stringa json. Quindi, posso facilmente tirare fuori i dischi e li mando al modello in questo modo:

echo $twig->render('template.html.twig', array(
     "layouts" => $layouts, 
)); 

Fin qui tutto bene, ma quando lo faccio la mia {% per il layout in layout%} nel ramo non v'è alcun modo per accedere agli elementi del campo proprietà poiché sono ancora una stringa json.

Quindi, poco prima ho passato $ layout per il modello ramoscello ho fatto la seguente:

foreach($layouts as $i => $v) 
{ 
     $layouts[$i]->decoded = json_decode($v->getProperties()); 
} 

facendo questo Ive ha creato una variabile al volo nel mio oggetto chiamato 'decodificati', che contiene l'oggetto JSON decodificato .

Così ora nel mio modello posso accedere al mio oggetti JSON da {{}} layout.decoded.whatever

Questo potrebbe essere un po 'hacky e non adatto a tutti i idea di una buona soluzione. Io lavoro bene per me, pochissimo overhead e significa che non devo scherzare con l'estensione del ramoscello mentre Sto facendo il lavoro prima che arrivi al modello.

2

Un alternativo a tutti sopra.
E non so se questa sia la soluzione ottimale, ma funziona .

1) Creare una funzione di supporto e registro che lo funzionano.

<?php 
function twig_json_decode($json) 
{ 
    return json_decode($json, true); 
} 


2) Usare questa funzione nel file di ramoscello.

{% set res = twig_json_decode(json) %} 
# above will return an array which can be iterated 

{% for r is res %} 
    {{ r }} 
{% endfor %} 
2

codice aggiornato per Symfony2.8 o 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'), 
     ]; 
    } 
} 
0

Nel mio caso ho avuto un JsonArray nel mio Entity allora ho aggiungere nel mio Entity un Methode

<?php 
namespace ACME\DefaultBundle\Entity; 
/*...*/  
public function getDecodedPath() 
{ 
    return json_decode($this->path); 
} 
-1

Per Symfony 3.1, come dice official doc, esiste un helper per questo scopo: 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()]); 
} 

L'output è simile:

{"name":"john","age":39} 
+0

Per il down -voter: ti piacerebbe elaborare il down-vote? –

0

Questa è una vecchia questione, ma sto aggiungendo la mia soluzione per la cronaca ... Basta estendere Ramoscello con un 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); 

Usage :

impostare a_json_variable nella stringa '["1", "2", "3", "4", "5"]' prima di richiamare il rendering di Twig.

modello

Twig:

The values are: {{ json_to_list(a_json_variable) }} 

produrrà

The values are: 1, 2, 3, 4, 5