我已经阅读了食谱RequestHandler
中的部分。有,等。但没有。isXml()
isRss()
isJson()
检查请求是否为 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 扩展名并相应地处理,那么你可以在你的控制器中做:
$this->request->params['ext']; //which would give you 'json' if you have .json extension
CakePHP 正确地处理了这个问题,因为 JSON 是一种响应类型而不是一种请求类型。术语请求和响应可能会引起一些混乱。request 对象表示发送给服务器的 HTTP 请求的头部信息。浏览器通常会向服务器发送 POST 或 GET 请求,这些请求不能被格式化为 JSON。因此,请求不可能是 JSON 类型。
话虽如此,服务器可以给出 JSON 响应,浏览器可以放入支持 JSON 响应的请求标头。因此,而不是检查请求是什么。检查浏览器支持哪些接受的响应。
所以$this->request->isJson()
你应该写而不是写$this->request->accepts('application/json')
。
此信息在此处的文档中显示不明确,但文档中没有参考see also
链接is(..)
。那么多人先看那里。看不到 JSON 并假设缺少某些东西。
如果您想使用请求检测器来检查浏览器是否支持 JSON 响应,那么您可以轻松地在 beforeFilter 中添加一个单行。
$this->request->addDetector('json',array('callback'=>function($req){return $req->accepts('application/json');}));
这种方法存在风险,因为浏览器可以发送多种响应类型作为来自服务器的可能响应。包括所有类型的通配符。因此,这将您限制为仅支持指示 JSON 响应的请求。由于 JSON 是一种文本格式,text/plain
因此对于需要 JSON 的浏览器来说,类型是有效的响应类型。
我们可以修改我们的规则以包含text/plain
这样的 JSON 响应。
$this->request->addDetector('json',array('callback'=>function($req){
return $req->accepts('application/json') || $req->accepts('text/plain');
}));
这将包括作为 JSON 响应类型的 text/plain 请求,但现在我们遇到了问题。仅仅因为浏览器支持 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 响应。
您可以制作自己的探测器。见: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();
您是否仔细阅读并遵循了书中非常详细的说明?:
http://book.cakephp.org/2.0/en/views/json-and-xml-views.html
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);
}
}
非常感谢@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')
));
}
}