8

我已经阅读了食谱RequestHandler中的部分。有,等。但没有。isXml()isRss()isJson()

检查请求是否为 JSON 的任何其他方法?

所以当 url 是mysite.com/products/view/1.json它会给出 JSON 数据,但没有.json它会给出 HTML 视图。

谢谢

4

6 回答 6

11

我不认为 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
于 2013-06-12T03:12:26.147 回答
8

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 响应。

于 2013-09-03T16:05:24.203 回答
4

您可以制作自己的探测器。见: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();
于 2013-06-27T08:06:56.197 回答
3

您是否仔细阅读并遵循了书中非常详细的说明?:

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

于 2013-06-12T03:11:42.067 回答
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);
    }
}
于 2014-09-09T04:04:08.963 回答
1

非常感谢@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')
            ));
        }
    }
于 2016-04-28T02:56:59.517 回答