2015-05-08 19 views
9

Ho configurato FOSRestBundle come segue:configurazione FOSRestBundle per JSON ritorno, ma ancora chiedendo template Twig

#FOSRestBundle 
fos_rest: 
    param_fetcher_listener: true 
    body_listener: true 
    format_listener: 
     rules: 
      - { path: ^/, priorities: [ json, html ], fallback_format: ~, prefer_extension: true } 
     media_type: 
      version_regex: '/(v|version)=(?P<version>[0-9\.]+)/' 

    body_converter: 
     enabled: true 
     validate: true 

    view: 
     mime_types: 
      json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1'] 
     view_response_listener: 'force' 
     formats: 
      xml: false 
      json: true 
     templating_formats: 
      html: true 

    exception: 
     codes: 
      'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404 
      'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT 
     messages: 
      'Symfony\Component\Routing\Exception\ResourceNotFoundException': true 
    allowed_methods_listener: true 
    access_denied_listener: 
     json: true 

E ho questo al controllore:

namespace PDI\PDOneBundle\Controller\Rest; 

use FOS\RestBundle\Controller\FOSRestController; 
use Nelmio\ApiDocBundle\Annotation\ApiDoc; 
use FOS\RestBundle\Controller\Annotations\QueryParam; 
use FOS\RestBundle\Controller\Annotations\Get; 

class RepresentativeRestController extends FOSRestController 
{ 
    /** 
    * Get all representatives. 
    * 
    * @return array 
    * 
    * @ApiDoc(
    * resource = true, 
    *  https = true, 
    * description = "Get all representatives.", 
    * statusCodes = { 
    *  200 = "Returned when successful", 
    *  400 = "Returned when errors" 
    * } 
    *) 
    * @Get("/api/v1/reps") 
    */ 
    public function getRepsAction() 
    { 
     $em = $this->getDoctrine()->getManager(); 
     $entities = $em->getRepository('PDOneBundle:Representative')->findAll(); 

     if(!$entities) 
     { 
      return $this->view(null, 400); 
     } 

     return $this->view($entities, 200); 
    } 
} 

Ma quando provo il seguente URL app_dev.php/api/v1/reps ho ottenuto questo errore:

Unable to find template "". 500 Internal Server Error - InvalidArgumentException 3 linked Exceptions: Twig_Error_Loader » InvalidArgumentException » InvalidArgumentException »

mi aspetto che API restituiscono un ben formato JSON un s il seguente esempio:

{ 
    "id":"30000001", 
    "veeva_rep_id":"0055648764067SwzAAE", 
    "display_name":"John Know", 
    "avatar_url":"http://freelanceme.net/Images/default%20profile%20picture.png", 
    "rep_type":"VEEVA", 
    "username":"[email protected]", 
    "first":"John", 
    "last":"Know", 
    "title":"Sales Representative", 
    "phone":"800-555-1212", 
    "email":"[email protected]", 
    "territory_id":"200454001", 
    "inactive":"no", 
    "total_contacts":"6", 
    "total_shares":"0", 
    "totalViews":"0", 
    "lastLoginAt":"2015-05-05 15:45:57", 
    "lastVeevaSyncAt":"2015-05-05 15:45:57", 
    "createdAt":"2015-05-05 15:45:57", 
    "updatedAt":"2015-05-05 15:45:57" 
} 

Non è configurato FOSRestBundle per restituire JSON? Perché chiedere ancora il modello Twig? Come posso risolvere questo?

Prima prova:

Come @Jeet mi suggeriscono Ho provato con Postman (è la stessa come l'estensione mi ha detto) e dopo impostare l'intestazione Content-Type al application/json l'errore si trasforma in questo

Malformed JSON

così, il FOSRestBundle non è la creazione di intestazioni come dovrebbe essere e il controller non è la restituzione di un JSON valida, come posso risolvere quelle?

Seconda prova:

Come suggerito da @Jeet ho eseguito questo test:

/** 
* Get all representatives. 
* 
* @return array 
* 
* @ApiDoc(
* resource = true, 
*  https = true, 
* description = "Get all representatives.", 
* statusCodes = { 
*  200 = "Returned when successful", 
*  400 = "Returned when errors" 
* } 
*) 
* @Get("/api/v1/reps") 
* @View() 
*/ 
public function getRepsAction() 
{ 
    $em = $this->getDoctrine()->getManager(); 
    $entities = $em->getRepository('PDOneBundle:Representative')->findAll(); 

    $temp = array("1", "2", "3"); 

    $view = $this->view($temp, Codes::HTTP_OK); 
    return $this->handleView($view); 
} 

E ancora lo stesso problema:

Unable to find template "". 500 Internal Server Error - InvalidArgumentException 3 linked Exceptions: Twig_Error_Loader » InvalidArgumentException » InvalidArgumentException »

Che altro può essere sbagliato Qui? Mi sono perso qualcosa durante la configurazione?

Ho dimenticato di aggiungere app/config/routing.yml e src/PDI/PDOneBundle/Resources/config/routing.yml in un primo momento ecco loro va, forse questo è il pezzo mancante del puzzle e vi darà una migliore idea di dove il problema proviene da:

#app/config/routing.yml 
#PDOne 
pdone: 
    resource: "@PDOneBundle/Resources/config/routing.yml" 

template: 
    resource: "@TemplateBundle/Resources/config/routing.yml" 

#FOSUserBundle 
fos_user: 
    resource: "@FOSUserBundle/Resources/config/routing/all.xml" 
    prefix:/

#NelmioApiDocBundle: 
NelmioApiDocBundle: 
    resource: "@NelmioApiDocBundle/Resources/config/routing.yml" 
    prefix: /api/doc 

#SonataAdmin 
admin: 
    resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml' 
    prefix: /admin 

_sonata_admin: 
    resource: . 
    type: sonata_admin 
    prefix: /admin 

#src/PDI/PDOneBundle/Resources/config/routing.yml 
pdone: 
    resource: "@PDOneBundle/Controller/" 
    type:  annotation 
    prefix: /

Terza prova :

Sicuramente qualcosa è sbagliato con la richiesta lato client, se uso uno strumento come Postman e impostare le intestazioni appropriate ho ottenuto le entità come voglio, vedi foto qui sotto:

enter image description here

non riesco a trovare dove il problema è così ho disperatamente bisogno di aiuto di qualcuno qui perché ero già a corto di idee

+0

Avete impostato "Content-Type" come "application/json"? – Jeet

+0

@Jeet dove dovrei farlo? Non è nella configurazione dei FOSR come puoi vedere sull'OP? – ReynierPM

+0

Prova app_dev.php/api/v1/ripetizioni nell'applicazione Advanced Rest Client di Google Chrome (estensione dell'app), qui avrai un'opzione. – Jeet

risposta

21

Come suggerito dai ragazzi: solo l'intestazione o l'estensione Accept può darti un JSON. Sembra che tu abbia risolto questo problema con l'intestazione Accept.

Per utilizzare l'estensione è necessario indicare come si desidera impostare le cose in formato in Symfony.

Questo codice dovrebbe darvi un output che si desidera:

namespace RestTestBundle\Controller; 

use FOS\RestBundle\Controller\Annotations\View; 

use FOS\RestBundle\Controller\Annotations\Get; 

class YourController 
{ 
    /** 
    * @Get("/api/v1/reps.{_format}", defaults={"_format"="json"}) 
    * @View() 
    */ 
    public function indexAction() 
    { 
     return array(
      'status' => 'ok', 
      'companies' => array(
       array('id' => 5), 
       array('id' => 7), 
      ), 
     ); 
    } 
} 

Edit1: se non si desidera utilizzare una classe View, ma le matrici puri: non dimenticare di non consentire Visualizza trattamento dei SensioExtraBundle

sensio_framework_extra: 
    view: { annotations: false } 

Edit2: Se non utilizzare il formato HTML e vogliono solo per avere un'uscita jSON è possibile utilizzare tale fonfiguration:

fos_rest: 
    # .... 
    format_listener: 
     rules: 
      - { path: ^/, priorities: [ json ], fallback_format: json, prefer_extension: true } 
    # .... 

spiegazione perché non vede un "punto di vista non trovato" errore:

TL; DR: il browser invia un'intestazione che dice FOSRestBundle per produrre una variante di 'html' Accetta.

Sfondo: questo pacchetto funziona principalmente con le intestazioni Accept, è buona norma disporre di tutti i formati di output disponibili: html (puoi testare l'API REST con i moduli che fornisci, elenchi di oggetti, dettagli di oggetti facilmente questo modo), json, xml. A volte anche i tipi di immagine mime come immagine/jpeg, immagine/png come default o json/xml come variante (puoi usare la rappresentazione dell'immagine base64).

Spiegazione: Se si apre una scheda "rete" di un browser e controllare le intestazioni invia noterete qualcosa di simile a: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 che significa "l'uso in tale ordine":

  1. text/html
  2. application/xhtml + xml
  3. application/xml con priorità 0,9 che è vietato in base al vostro c ONFIGURAZIONE
  4. */* con priorità 0,8 che meand qualsiasi formato

Se si guarda vicino a questo è vedrete che in base alla configurazione text/html è una delle varianti che il vostro configurazione ha ('html') e */* è un altro ('json'), ma text/html ha una priorità di 1, mentre */* ha una priorità pari a 0.8, quindi text/html corrispondenze e FOSRestBundle tenta di trovare una rappresentazione HTML e non riesce.

PS: se postate domande più volte, assicuratevi di controllare tutte le risposte in ogni thread.

+0

Ottima risposta Artem L !! Mi ha aiutato molto ... Grazie mille .. –

1

FosRestBundle sfrutta la Accetta intestazione. Ciò significa che restituisce una risposta in base a ciò che viene richiesto. Accedendo al percorso "app_dev.php/api/v1/reps", stai richiedendo implicitamente un formato html, quindi prova a fornire un modello.

Does app_dev.php/API/v1/ripetizioni.JSON restituisci quello che ti serve?

Si dovrebbe anche provare app_dev.php/api/v1/reps.xml e si aspettano un output XML

+1

Nessuno di quei tre funziona per me, quando inserisco '.html' o' .json' o '.xml' ho 404 errori di percorso, non riesco a trovare quello che mi manca nella mia configurazione o sul lato controller – ReynierPM

+0

La tua risposta ha la soluzione ma è implicita nel contenuto. Dovresti specificarlo per testare con alcuni client come Chrome/Firefox RestClient estensione Uno DEVE impostare l'intestazione corretta: Accetta: application/json – le0diaz

2

Si può dare risposta in due modi

return View::create($entities, Codes::HTTP_OK); 

o

$view = $this->view($entities, Codes::HTTP_OK);  
return $this->handleView($view) 
+0

In questo modo funziona, ma solo dall'estensione di Postman Chrome impostando le intestazioni giuste per 'Content-Type 'se provo dal browser ho avuto lo stesso problema con il template che mi fa chiedere: perché? dove si trova il problema sulla configurazione e perché l'installazione delle intestazioni non è corretta? Mi piace anche restituire una sorta di 'NotFoundException' se non ci sono' $ entity', puoi mostrarmi come ottenerlo sul tuo codice? – ReynierPM

Problemi correlati