2012-03-01 21 views
61

Sto lavorando a un progetto utilizzando Symfony 2, ho creato un pacchetto per gestire tutti i miei servizi di database che trasmettono i dati JSON avanti e indietro.Invio di oggetti JSON a Symfony 2

mio Problema/Domanda:

  • E 'possibile inserire un oggetto JSON su diritto? Attualmente sto spoofing un post forma normale per i miei chiamate ajax dando l'oggetto un nome json={"key":"value"} se non me ne frega un nome che non riesco a ottenere i dati dalla richiesta oggetto Symfony $JSON = $request->request->get('json');

  • I vuole essere in grado di utilizzare l'unico pacchetto di servizi per gestire sia i dati provenienti da chiamate AJAX, sia un normale modulo Symfony. Attualmente sto prendendo il modulo inviato da Symfony, ottenendo i dati usando quindi JSON_ENCODE, non riesco proprio a capire come inviare i dati attraverso il controller dei servizi che si aspetta dati delle richieste.

In sintesi:

  • voglio Symfony ad accettare un oggetto JSON messaggio piuttosto che un modulo.

  • voglio passare l'oggetto JSON tra controllori mediante richiesta/risposta

Se sto andando su questo tutto sbagliato, non esitate a dirmelo!

risposta

120

Se si desidera recuperare i dati in vostro controller che è stato inviato come standard JSON nel corpo della richiesta, si può fare qualcosa di simile a quanto segue:

public function yourAction() 
{ 
    $params = array(); 
    $content = $this->get("request")->getContent(); 
    if (!empty($content)) 
    { 
     $params = json_decode($content, true); // 2nd param to get as array 
    } 
} 

Ora $params sarà un allineamento completo dei tuoi dati JSON. Rimuovere il valore del parametro true nella chiamata json_decode() per ottenere un oggetto stdClass.

+0

Grazie per la risposta. In realtà ho funzionato nel weekend in questo modo: $ JSON = file_get_contents ("php: // input"); Eventuali problemi in questo modo? – greg

+17

'php: // input' è una sola lettura. Una volta letto il contenuto, non è più possibile rileggere a meno che non vengano trasmessi tali dati. L'utilizzo dell'oggetto Symfony2 Request garantisce che è possibile ottenere di nuovo i dati durante una richiesta, se necessario, senza passare ad esempio la variabile '$ JSON'. – richsage

+0

Grazie per la spiegazione! Sono cambiato con il tuo metodo e funziona perfettamente. Grazie. – greg

1

javascript pagina:

function submitPostForm(url, data) { 
    var form    = document.createElement("form"); 
     form.action   = url; 
     form.method   = 'POST'; 
     form.style.display = 'none'; 

    //if (typeof data === 'object') {} 

    for (var attr in data) { 
     var param  = document.createElement("input"); 
      param.name = attr; 
      param.value = data[attr]; 
      param.type = 'hidden'; 
     form.appendChild(param); 
    } 

    document.body.appendChild(form); 
    form.submit(); 
} 

dopo qualche evento (come un clic su "submit"):

// products is now filled with a json array 
var products = jQuery('#spreadSheetWidget').spreadsheet('getProducts'); 
var postData = { 
'action': action, 
'products': products 
} 
submitPostForm(jQuery('#submitURLcreateorder').val(), postData); 

nel controller:

/** 
    * @Route("/varelager/bestilling", name="_varelager_bestilling") 
    * @Template() 
    */ 
    public function bestillingAction(Request $request) { 
     $products = $request->request->get('products', null); // json-string 
     $action  = $request->request->get('action', null); 

     return $this->render(
      'VarelagerBundle:Varelager:bestilling.html.twig', 
      array(
       'postAction' => $action, 
       'products' => $products 
      ) 
     ); 
    } 

nel modello (bestilling.html.twig nel mio caso):

{% block resources %} 
     {{ parent() }} 
     <script type="text/javascript"> 
     jQuery(function(){ 
      //jQuery('#placeDateWidget').placedate(); 
      {% autoescape false %} 
      {% if products %} 

      jQuery('#spreadSheetWidget').spreadsheet({ 
       enable_listitem_amount: 1, 
       products: {{products}} 
      }); 
      jQuery('#spreadSheetWidget').spreadsheet('sumQuantities'); 
      {% endif %} 
      {% endautoescape %} 

     }); 
     </script> 
    {% endblock %} 

Alrite, penso che è quello che si voleva :)

EDIT Per inviare qualcosa senza la simulazione di un modulo è possibile utilizzare jQuery.ajax(). Ecco un esempio con lo stesso spirito di cui sopra che non innescherà un aggiornamento della pagina.

jQuery.ajax({ 
    url:  jQuery('#submitURLsaveorder').val(), 
    data:  postData, 
    success: function(returnedData, textStatus, jqXHR){ 
     jQuery('#spreadSheetWidget').spreadsheet('clear'); 
     window.alert("Bestillingen ble lagret"); 
     // consume returnedData here 

    }, 
    error:  jQuery.varelager.ajaxError, // a method 
    dataType: 'text', 
    type:  'POST' 
}); 
+0

Grazie per la rapida risposta! Essenzialmente stai ancora inviando un modulo normale con javascript, che è quello che sto facendo al momento, mi stavo chiedendo se fosse possibile postare direttamente l'oggetto JSON senza simulare un modulo, se non senza drammi. Inoltre, una volta ottenuto l'oggetto JSON in Symfony, è possibile inviarlo ad un altro servizio come oggetto Richiesta? – greg

+0

Ho indirizzato il tuo commento nella mia modifica. Non sono abbastanza sicuro di come fare una roba jax senza jQuery, quindi ammettilo. Per inviare qualcuno a un altro controller, puoi reindirizzare lì. Questo è spiegato in http://symfony.com/doc/2.0/book/controller.html in * Reindirizzamento * e * Inoltro *. In bocca al lupo! –

+0

Grazie ancora, avrei dovuto essere un po 'più chiaro, posso inviare l'oggetto senza problemi, non riesco proprio a capire come recuperarlo nel controller senza che abbia un nome – greg

6

ho scritto metodo per ottenere contenuti come matrice

protected function getContentAsArray(Request $request){ 
    $content = $request->getContent(); 

    if(empty($content)){ 
     throw new BadRequestHttpException("Content is empty"); 
    } 

    if(!Validator::isValidJsonString($content)){ 
     throw new BadRequestHttpException("Content is not a valid json"); 
    } 

    return new ArrayCollection(json_decode($content, true)); 
} 

e io uso questo metodo come illustrato di seguito

$content = $this->getContentAsArray($request); 
$category = new Category(); 
$category->setTitle($content->get('title')); 
$category->setMetaTitle($content->get('meta_title')); 
+1

La classe validatore esiste per impostazione predefinita su symfony? –

+0

no, è una classe personalizzata –