2013-06-12 14 views
6

Ho letto la parte RequestHandler in cookbook. Ci sono isXml(), isRss(), ecc. Ma non c'è lo isJson().Cakephp - Se la richiesta è JSON?

Qualsiasi altro modo per verificare se una richiesta è JSON?

Così quando l'url è mysite.com/products/view/1.json darà dati JSON, ma senza .json darà la visualizzazione HTML.

Grazie

risposta

10

Non penso cakePHP ha qualche funzione come isJson() per i dati JSON, si potrebbe creare la vostra abitudine se, come:

//may be in your app controller 
function isJson($data) { 
    return (json_decode($data) != NULL) ? true : false; 
} 
//and you can use it in your controller 
if($this->isJson($your_request_data)) { 
... 
} 

Aggiunto: se si desidera controllare .json extens di conseguenza, è possibile farlo nel proprio controller:

$this->request->params['ext']; //which would give you 'json' if you have .json extension 
+0

Grazie per la risposta, forse la mia domanda è un po 'confusa. Voglio che il sito restituisca i dati JSON quando ha '.json' alla fine dell'URL, altrimenti restituisce il normale HTML View – hrsetyono

+1

sei il benvenuto .. :) –

4

Hai guardato attraverso e seguito le istruzioni molto dettagliate nel libro ?:

http://book.cakephp.org/2.0/en/views/json-and-xml-views.html

+1

Non penso che ho bisogno visualizzazione personalizzata per questo dato che ho solo bisogno il risultato puro query di database. Ma se questo è l'unico modo, suppongo che lo seguirò. Quindi nel mio 'controller', non ho bisogno di alcuna istruzione' if' che dice 'if (json) render this'? – hrsetyono

+0

Non è necessario utilizzare una vista personalizzata se si desidera rispondere con json. Ti stanno solo dicendo che * puoi * usare una vista personalizzata. Usando Router :: parseExtensions ('json') e caricando RequestHandler nel tuo controller, puoi semplicemente scrivere '$ this-> set ('product', $ product); $ this-> set ('_ serialize', 'product'); 'e risponderà automagicamente con json se la tua richiesta ha un'intestazione' Accept: application/json' o renderizza il file di visualizzazione se la tua richiesta ha 'Accept: text/html'. Non dovresti controllare è ('digita') tutto il tempo perché la negoziazione del tipo di contenuto può essere gestita per te! – jbielick

4

È possibile creare i propri rilevatori. Vedere: http://book.cakephp.org/2.0/en/controllers/request-response.html#inspecting-the-request

Ad esempio nella tua AppController.php

public function beforeFilter() { 
    $this->request->addDetector(
    'json', 
    [ 
     'callback' => [$this, 'isJson'] 
    ] 
); 
    parent::beforeFilter(); 
} 

public function isJson() { 
    return $this->response->type() === 'application/json'; 
} 

Ora è possibile utilizzarlo:

$this->request->is('json'); // or 
$this->request->isJson(); 
+0

Ciao Grazie, proverò ad usarlo quando ho bisogno di questo funzione di nuovo. – hrsetyono

6

CakePHP sta gestendo correttamente, perché JSON è un tipo di risposta e non un tipo di richiesta I termini richiesta e risposta potrebbero causare confusione. L'oggetto request rappresenta le informazioni di intestazione della richiesta HTTP inviata al server. Generalmente un browser invia richieste POST o GET a un server e tali richieste possono essere non essere formattate come JSON. Quindi non è possibile che una richiesta sia di tipo JSON.

Detto ciò, il server può fornire una risposta di JSON e un browser può inserire nell'intestazione della richiesta che supporta una risposta JSON. Quindi, piuttosto che controllare quale fosse la richiesta. Verifica quali risposte accettate sono supportate dal browser.

Quindi, anziché scrivere $this->request->isJson(), è necessario scrivere $this->request->accepts('application/json').

Queste informazioni sono visualizzate in modo ambiguo nello document here, ma non vi sono riferimenti see also nella documentazione is(..). Così tante persone ci guardano prima. Non vedere JSON e supponiamo che manchi qualcosa.

Se si desidera utilizzare un rilevatore di richieste per verificare se il browser supporta una risposta JSON, è possibile aggiungere facilmente un solo liner in beforeFilter.

$this->request->addDetector('json',array('callback'=>function($req){return $req->accepts('application/json');})); 

V'è un rischio associato a questo approccio, perché un browser può inviare più tipi di risposta come una possibile risposta dal server. Compreso un carattere jolly per tutti i tipi. Quindi questo limita solo le richieste che indicano che una risposta JSON è supportata.Poiché JSON è un formato di testo, un tipo di text/plain è un tipo di risposta valido per un browser che si aspetta JSON.

Potremmo modificare la nostra regola per includere text/plain per le risposte JSON come questa.

$this->request->addDetector('json',array('callback'=>function($req){ 
    return $req->accepts('application/json') || $req->accepts('text/plain'); 
})); 

Ciò include le richieste di testo/semplici come un tipo di risposta JSON, ma ora abbiamo un problema. Solo perché il browser supporta una risposta testuale/semplice non significa che si aspetta una risposta JSON.

Ecco perché è meglio incorporare una convenzione di denominazione nel proprio URL per indicare una risposta JSON. È possibile utilizzare un'estensione di file .json o un prefisso /json/controller/action.

Preferisco utilizzare un prefisso denominato per gli URL. Ciò consente di creare metodi json_action nel controller. È quindi possibile creare un rilevatore per il prefisso come questo.

$this->request->addDetector('json',array('callback'=>function($req){return isset($req->params['prefix']) && $req->params['prefix'] == 'json';})); 

Ora che rilevatore sarà sempre funziona correttamente, ma io sostengo che è un uso non corretto di rilevare una richiesta JSON. Poiché non esiste una richiesta JSON. Solo le risposte JSON.

+1

Ciao grazie per la risposta. Cancella una certa confusione che ho avuto. – hrsetyono

1
class TestController extends Controller { 

    public $autoRender = false; 

    public function beforeFilter() { 
     $this->request->addDetector('json', array('env' => 'CONTENT_TYPE', 'pattern' => '/application\/json/i')); 
     parent::beforeFilter(); 
    } 

    public function index() { 
     App::uses('HttpSocket', 'Network/Http'); 

     $url = 'http://localhost/myapp/test/json'; 
     $json = json_encode(
      array('foo' => 'bar'), 
      JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP 
     ); 
     $options = array('header' => array('Content-Type' => 'application/json')); 

     $request = new HttpSocket(); 
     $body = $request->post($url, $json, $options)->body; 

     $this->response->body($body); 
    } 

    public function json() { 

     if ($this->request->isJson()) { 
      $data = $this->request->input('json_decode'); 
      $value = property_exists($data, 'foo') ? $data->foo : ''; 
     } 

     $body = (isset($value) && $value === 'bar') ? 'ok' : 'fail'; 
     $this->response->body($body); 
    } 
} 
+0

Grazie per l'aggiunta. Questo sarà utile per gli altri – hrsetyono

1

Grazie mille Mr @ Schlafer. Leggo il tuo commento e prova, Wow funziona ora.

//AppController.php 

function beforeFilter() { 
     $this->request->addDetector(
       'json', [ 
      'callback' => [$this, 'isJson'] 
       ] 
     ); 
     parent::beforeFilter(); 
     ... 
    } 


public function isJson() { 
     return $this->response->type() === 'application/json'; 
    } 
//TasksController.php 

public $components = array('Paginator', 'Flash', Session','RequestHandler'); 

// Get funzione di compiti restituire tutte le attività in formato JSON

public function getTasks() { 
     $limit = 20; 
     $conditions = array(); 
     if (!empty($this->request->query['status'])) { 
      $conditions = ['Task.status' => $this->request->query['status']]; 
     } 
     if (!empty($this->request->query['limit'])) { 
      $limit = $this->request->query['limit']; 
     } 
     $this->Paginator->settings = array('limit' => $limit, 'conditions' => $conditions); 

     $tasks = $this->paginate(); 

     if ($this->request->isJson()) { 

      $this->set(
array(
       'tasks' => $tasks, 
       '_serialize' => array('tasks') 
      )); 
     } 
    } 
Problemi correlati