CakePHP - if JSON request?

I read the RequestHandler part in the cookbook . There are isXml() , isRss() , etc. But there is no isJson() .

Any other way to check if the request is JSON?

So, when url is mysite.com/products/view/1.json , it will give JSON data, but without .json it will provide HTML representation.

thanks

+6
source share
6 answers

I don't think cakePHP has some function like isJson () for json data, you can create your own though:

 //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) ) { ... } 

Added: if you want to check the .json extension and process accordingly, then you can do in your controller:

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

CakePHP handles this correctly because JSON is the response type, not the request type. The terms of the request and response may lead to some confusion. The request object represents the header information of the HTTP request sent to the server. The browser usually sends POST or GET requests to the server, and these requests cannot be formatted as JSON. Therefore, the request cannot be of type JSON.

With that said, the server can give a JSON response, and the browser can put the request header so that it supports the JSON response. Therefore, instead of checking what the request is. Check which accepted answers are supported by the browser.

So instead of writing $this->request->isJson() you should write $this->request->accepts('application/json') .

This information is ambiguously shown in the document here , but see also links in the is(..) documentation are missing see also links. So many people look there first. You do not see JSON and assume that something is missing.

If you want to use the request detector to check if the browser supports JSON response, you can easily add one insert to your beforeFilter file.

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

There is a risk associated with this approach, as the browser may send several types of responses as a possible response from the server. Includes wildcard for all types. Thus, this limits you to only requests pointing to a JSON response. Since JSON is a text format, the text/plain type is a valid response type for a browser that expects JSON.

We could modify our rule to include text/plain for JSON responses like this.

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

This will include text / simple requests as a JSON response type, but now we have a problem. Just because the browser supports a text / simple response does not mean that it expects a JSON response.

That's why it's better to include a naming convention in your URL to indicate a JSON response. You can use the .json file .json or the /json/controller/action prefix.

I prefer using a named prefix for URLs. This allows you to create json_action methods in your controller. You can then create a detector for this prefix.

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

Now this detector will always work correctly, but I claim that it is a misuse of JSON request detection. Since there is no such thing as a JSON request. Only JSON responses.

+6
source

Have you viewed and followed the very detailed instructions in the book ?:

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

+4
source

You can create your own detectors. See: http://book.cakephp.org/2.0/en/controllers/request-response.html#inspecting-the-request

For example, in your AppController.php

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

Now you can use it:

 $this->request->is('json'); // or $this->request->isJson(); 
+4
source
 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); } } 
+1
source

Many thanks to Mr. @ Schlefer. I read your comment and try, Wow it works now.

 //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 tasks function returns all tasks in json format

 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') )); } } 
+1
source

Source: https://habr.com/ru/post/947070/


All Articles