我已閱讀cookbook中的RequestHandler
部分。有isXml()
,isRss()
等,但沒有isJson()
。Cakephp - 如果請求是JSON?
任何其他方式來檢查請求是否是JSON?
所以當url是mysite.com/products/view/1.json
它會給JSON數據,但沒有.json
它會給HTML視圖。
感謝
我已閱讀cookbook中的RequestHandler
部分。有isXml()
,isRss()
等,但沒有isJson()
。Cakephp - 如果請求是JSON?
任何其他方式來檢查請求是否是JSON?
所以當url是mysite.com/products/view/1.json
它會給JSON數據,但沒有.json
它會給HTML視圖。
感謝
我不認爲CakePHP有像isJson()用於JSON數據的一些功能非常詳細的說明,你可以雖然創建自定義,如:
//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)) {
...
}
補充: 如果您要檢查以.json EXTENS離子和相應的過程,那麼你可以在你的控制器:
$this->request->params['ext']; //which would give you 'json' if you have .json extension
你有沒有看遍了,跟着書中?:
http://book.cakephp.org/2.0/en/views/json-and-xml-views.html
我不認爲我需要爲這個自定義視圖,因爲我只需要從數據庫中純查詢結果。但如果這是唯一的方法,我想我會遵循它。所以在我的'控制器',我不需要任何'if'語句,像'if(json)渲染這個'? – hrsetyono
如果您想用json響應,您不需要使用自定義視圖。他們只是告訴你,你*可以*使用自定義視圖。通過使用Router :: parseExtensions('json')並在你的控制器中加載RequestHandler,你可以簡單地寫'$ this-> set('product',$ product); $ this-> set('_ serialize','product');'如果你的請求有一個'Accept:application/json'頭文件,它會自動響應json,或者如果你的請求有'Accept:text/html'。您不應該一直檢查是否('類型'),因爲可以爲您處理內容類型協商! – jbielick
你可以使自己的探測器。請參閱:http://book.cakephp.org/2.0/en/controllers/request-response.html#inspecting-the-request
例如,在您的AppController.php
public function beforeFilter() {
$this->request->addDetector(
'json',
[
'callback' => [$this, 'isJson']
]
);
parent::beforeFilter();
}
public function isJson() {
return $this->response->type() === 'application/json';
}
現在你可以使用它:
$this->request->is('json'); // or
$this->request->isJson();
嗨,謝謝,我會嘗試在我需要的時候使用它再次起作用。 – hrsetyono
CakePHP會正確處理這一點,因爲JSON是一個響應類型,而不是一個類型的請求。條款請求和響應可能會造成一些混淆。請求對象表示發送給服務器的HTTP請求的頭信息。瀏覽器通常會向服務器發送POST或GET請求,並且這些請求可以將而不是格式化爲JSON。所以對於請求來說JSON類型是不可能的。
隨着中說,該服務器可以給JSON的響應和瀏覽器可以把它支持的JSON響應請求頭。所以而不是檢查請求是什麼。檢查瀏覽器支持哪些接受的響應。
所以不是寫作$this->request->isJson()
你應該寫$this->request->accepts('application/json')
。
此信息模糊地顯示在document here中,但is(..)
文檔中沒有提及see also
鏈接。很多人首先看那裏。沒有看到JSON,並假設缺少一些東西。
如果你想使用一個請求檢測檢查,如果瀏覽器支持JSON響應,那麼你可以很容易地在您的beforeFilter添加一行。
$this->request->addDetector('json',array('callback'=>function($req){return $req->accepts('application/json');}));
有這種方法相關的風險,因爲瀏覽器可以發送多個響應類型爲來自服務器的響應可能。包括所有類型的通配符。因此,這會將您限制爲只顯示支持JSON響應的請求。由於JSON是文本格式,因此對於期望使用JSON的瀏覽器,text/plain
類型是有效的響應類型。
我們可以修改我們的規則以包含text/plain
這樣的JSON響應。
$this->request->addDetector('json',array('callback'=>function($req){
return $req->accepts('application/json') || $req->accepts('text/plain');
}));
這將包括text/plain的請求作爲一個JSON響應類型,但現在我們有一個問題。僅僅因爲瀏覽器支持text/plain響應並不意味着它期待JSON響應。
這就是爲什麼最好在您的URL中加入命名約定來表示JSON響應。您可以使用.json
文件擴展名或/json/controller/action
前綴。
我更喜歡使用URL的命名前綴。這允許您在控制器中創建json_action
方法。然後你可以像這樣爲前綴創建一個檢測器。
$this->request->addDetector('json',array('callback'=>function($req){return isset($req->params['prefix']) && $req->params['prefix'] == 'json';}));
現在探測器將始終正常工作,但我認爲它是檢測一個JSON請求不正確的用法。由於沒有這樣的東西作爲JSON請求。只有JSON響應。
嗨,謝謝你的回答。它清除了我的一些困惑。 – hrsetyono
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);
}
}
感謝您的補充。這對其他人很有用 – hrsetyono
非常感謝@Schlaefer先生。我閱讀你的評論並嘗試,哇現在正在工作。
//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');
//獲取任務的函數返回的所有任務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')
));
}
}
感謝您的回答,也許我的問題有點混亂。我希望網站在URL末尾有'.json'時返回JSON數據,否則返回正常HTML視圖 – hrsetyono
歡迎您.. :) –