2012-03-01 14 views
61

Pracuję nad projektem przy użyciu Symfony 2, zbudowałem pakiet do obsługi wszystkich moich usług baz danych, które przekazują dane JSON w przód iw tył.Wysyłanie obiektów JSON do Symfony 2

My Problem/Pytanie:

  • Czy to możliwe, aby umieścić prosto obiekt JSON? Obecnie jestem fałszowanie formą normalną wiadomość dla moich ajax połączeń poprzez nadanie obiektowi nazwę json={"key":"value"} jeśli nie daję mu nazwę I nie może wydawać się uzyskać dane z żądania obiektu Symfony $JSON = $request->request->get('json');

  • I chcą mieć możliwość korzystania z jednego pakietu usług do obsługi zarówno danych pochodzących z wywołań AJAX, jak i zwykłego formularza Symfony. Obecnie biorę zgłoszony formularz Symfony, pobierając dane, a następnie używając JSON_ENCODE, po prostu nie mogę się dowiedzieć, jak opublikować dane w moim kontrolerze usług, który oczekuje danych o żądaniu.

Podsumowując:

  • Chcę Symfony zaakceptować obiekt JSON pocztowy zamiast formularza.

  • Chcę przekazać obiekt JSON między kontrolerami użyciu żądanie/odpowiedź

Jeśli mam o tym wszystkim źle, nie krępuj się powiedzieć tak!

Odpowiedz

120

Jeśli chcesz odzyskać dane w kontrolerze, który został wysłany w standardzie JSON w organizmie żądanie, można zrobić coś podobnego do poniższego:

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

Teraz $params będzie tablicą pełne swoich danych JSON. Usuń wartość parametru true w wywołaniu json_decode(), aby uzyskać obiekt stdClass.

+0

Dzięki za odpowiedź. Tak naprawdę pracowałem przez weekend w ten sposób: $ JSON = file_get_contents ("php: // input"); Jakiekolwiek problemy z robieniem tego w ten sposób? – greg

+17

'php: // input' jest jednorazowym tylko do odczytu. Po przeczytaniu treści nie będzie można jej ponownie przeczytać, chyba że przekażesz te dane. Korzystanie z obiektu Symfony2 Request zapewnia, że ​​możesz uzyskać dane ponownie podczas żądania, jeśli zajdzie potrzeba, bez przekazywania np. Zmiennej '$ JSON'. – richsage

+0

Dzięki za wyjaśnienie! Zmieniłem twoją metodę i działa idealnie. Dziękuję Ci. – greg

1

javascript na stronie:

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

po pewnym przypadku (jak kliknij "wyślij"):

// 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); 

w kontrolerze:

/** 
    * @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 
      ) 
     ); 
    } 

w szablonie (bestilling.html.twig w moim przypadku):

{% 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, myślę, że to, co chciał :)

EDIT wysłać coś bez symulowania formularza można użyć jQuery.ajax(). Oto przykład w tym samym duchu, co powyżej, który nie spowoduje odświeżenia strony.

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

Dzięki za szybką odpowiedź! Zasadniczo nadal przesyłasz normalną formę za pomocą javascript, co jest w pewnym sensie tym, co robię w tej chwili, zastanawiałem się, czy możliwe było bezpośrednie umieszczenie obiektu JSON bez symulacji formularza, jeśli nie dramatu. Ponadto, gdy już mam obiekt JSON w Symfony, czy możliwe jest wysłanie go do innej usługi jako obiektu żądania? – greg

+0

Zaadresowałem twój komentarz w mojej edycji. Nie jestem całkiem pewien, jak zrobić rzeczy ajax bez jQuery, więc źle to zostawię. Aby wysłać kogoś do innego kontrolera, możesz go tam przekierować. Obejmuje to http://symfony.com/doc/2.0/book/controller.html pod * Przekierowanie * i * Przekierowanie *. Powodzenia! –

+0

Jeszcze raz dziękuję, powinienem być trochę jaśniejszy, mogę przesłać obiekt bez problemów, po prostu nie mogę się dowiedzieć, jak go pobrać w kontrolerze bez jego nazwy – greg

6

pisałem sposób, aby uzyskać jak zawartość tablicy

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

I skorzystać z tej metody, jak pokazano poniżej

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

Klasa walidatora istnieje domyślnie w symfony? –

+0

nie jest to klasa niestandardowa –