用CakePHP服务JSONP的正确方法是什么?

时间:2021-02-06 14:29:35

I want to serve JSONP content with CakePHP and was wondering what's the proper way of doing it so.

我想用CakePHP来提供JSONP内容,我想知道这样做的正确方式是什么。

Currently I'm able to serve JSON content automatically by following this CakePHP guide.

目前,我可以按照这个CakePHP指南自动地提供JSON内容。

3 个解决方案

#1


4  

I've as yet not found a complete example of how to correctly return JSONP using CakePHP 2, so I'm going to write it down. OP asks for the correct way, but his answer doesn't use the native options available now in 2.4. For 2.4+, this is the correct method, straight from their documentation:

我还没有找到一个完整的例子来说明如何正确地使用CakePHP 2返回JSONP,所以我要把它写下来。OP要求正确的方法,但是他的答案并没有使用现在2.4中可用的本机选项。对于2.4+,这是正确的方法,直接从他们的文档:

  1. Set up your views to accept/use JSON (documentation):

    设置视图以接受/使用JSON(文档):

    • Add Router::parseExtensions('json'); to your routes.php config file. This tells Cake to accept .json URI extensions
    • 添加路由器:parseExtensions(json);你的路线。php配置文件。这告诉Cake接受.json URI扩展。
    • Add RequestHandler to the list of components in the controller you're going to be using
    • 将RequestHandler添加到将要使用的控制器中的组件列表
    • Cake gets smart here, and now offers you different views for normal requests and JSON/XML etc. requests, allowing you flexibility in how to return those results, if needed. You should now be able to access an action in your controller by:
      • using the URI /controller/action (which would use the view in /view/controller/action.ctp), OR
      • 使用URI /controller/action(它将使用/view/controller/action.ctp中的视图),或
      • using the URI /controller/action.json (which would use the view in /view/controller/json/action.ctp)
      • 使用URI /控制器/动作。json(它将使用/视图/控制器/json/action.ctp)
    • Cake在这里很聪明,现在可以为正常的请求和JSON/XML等请求提供不同的视图,如果需要,您可以灵活地返回这些结果。您现在应该能够通过以下方式访问控制器中的操作:使用URI /controller/action(它将使用/view/controller/action.ctp中的视图),或者使用URI /controller/action。json(它将使用/视图/控制器/json/action.ctp)
  2. If you don't want to define those views i.e. you don't need to do any further processing, and the response is ready to go, you can tell CakePHP to ignore the views and return the data immediately using _serialize. Using _serialize will tell Cake to format your response in the correct format (XML, JSON etc.), set the headers and return it as needed without you needing to do anything else (documentation). To take advantage of this magic:

    如果您不想定义这些视图,也就是说,您不需要进行任何进一步的处理,并且响应已经准备就绪,您可以告诉CakePHP忽略这些视图,并使用_serialize立即返回数据。使用_serialize将告诉Cake以正确的格式(XML、JSON等)格式化您的响应,设置标题并在需要时返回,而不需要做任何其他事情(文档)。利用这个魔法:

    • Set the variables you want to return as you would a view variable i.e. $this->set('post', $post);
    • 设置要返回的变量,就像设置视图变量一样,即$this->集合('post', $post);
    • Tell Cake to serialize it into XML, JSON etc. by calling $this->set('_serialize', array('posts'));, where the parameter is the view variable you just set in the previous line
    • 通过调用$this->set('_serialize', array('posts')),告诉Cake将其序列化为XML、JSON等;在这里,参数是您刚刚设置在前一行中的视图变量。

And that's it. All headers and responses will be taken over by Cake. This just leaves the JSONP to get working (documentation):

就是这样。所有标题和响应将由Cake接管。这让JSONP开始工作(文档):

  1. Tell Cake to consider the request a JSONP request by setting $this->set('_jsonp', true);, and Cake will go find the callback function name parameter, and format the response to work with that callback function name. Literally, setting that one parameter does all the work for you.
  2. 通过设置$this->set('_jsonp', true),告诉Cake考虑JSONP请求的请求;Cake将找到回调函数名参数,并格式化响应以使用回调函数名。实际上,设置一个参数就可以完成所有的工作。

So, assuming you've set up Cake to accept .json requests, this is what your typical action could look like to work with JSONP:

因此,假设您已经设置了Cake来接受.json请求,这就是您使用JSONP时的典型动作:

public function getTheFirstPost()

    $post = $this->Post->find('first');

    $this->set(array(
        'post' => $post,                 <-- Set the post in the view
        '_serialize' => array('post'),   <-- Tell cake to use that post
        '_jsonp' => true                 <-- And wrap it in the callback function
    )
);

And the JS:

JS:

$.ajax({
    url: "/controller/get-the-first-post.json",
    context: document.body,
    dataType: 'jsonp'
}).done(function (data) {
    console.log(data);
});

#2


5  

Ok, I found a solution on this site. Basically you override the afterFilter method with:

我在这个网站上找到了解决方案。基本上你用以下方法覆盖afterFilter方法:

public function afterFilter() {
    parent::afterFilter();

    if (empty($this->request->query['callback']) || $this->response->type() != 'application/json') {
        return;
    }

    // jsonp response
    App::uses('Sanitize', 'Utility');
    $callbackFuncName = Sanitize::clean($this->request->query['callback']);
    $out = $this->response->body();
    $out = sprintf("%s(%s)", $callbackFuncName, $out);
    $this->response->body($out);
}

I hope it helps someone else as well.

我希望它也能帮助别人。

#3


0  

For CakePHP 2.4 and above, you can do this instead.

对于CakePHP 2.4和以上版本,您可以这样做。

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

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

So you can simply write:

你可以这样写:

$this->set('_jsonp', true);

in the relevant action.

在相关的行动。

Or you can simply write:

或者你可以简单地写:

/**
 *
 * beforeRender method
 *
 * @return void
 */
    public function beforeRender() {
        parent::beforeRender();
        $this->set('_jsonp', true);
    }

#1


4  

I've as yet not found a complete example of how to correctly return JSONP using CakePHP 2, so I'm going to write it down. OP asks for the correct way, but his answer doesn't use the native options available now in 2.4. For 2.4+, this is the correct method, straight from their documentation:

我还没有找到一个完整的例子来说明如何正确地使用CakePHP 2返回JSONP,所以我要把它写下来。OP要求正确的方法,但是他的答案并没有使用现在2.4中可用的本机选项。对于2.4+,这是正确的方法,直接从他们的文档:

  1. Set up your views to accept/use JSON (documentation):

    设置视图以接受/使用JSON(文档):

    • Add Router::parseExtensions('json'); to your routes.php config file. This tells Cake to accept .json URI extensions
    • 添加路由器:parseExtensions(json);你的路线。php配置文件。这告诉Cake接受.json URI扩展。
    • Add RequestHandler to the list of components in the controller you're going to be using
    • 将RequestHandler添加到将要使用的控制器中的组件列表
    • Cake gets smart here, and now offers you different views for normal requests and JSON/XML etc. requests, allowing you flexibility in how to return those results, if needed. You should now be able to access an action in your controller by:
      • using the URI /controller/action (which would use the view in /view/controller/action.ctp), OR
      • 使用URI /controller/action(它将使用/view/controller/action.ctp中的视图),或
      • using the URI /controller/action.json (which would use the view in /view/controller/json/action.ctp)
      • 使用URI /控制器/动作。json(它将使用/视图/控制器/json/action.ctp)
    • Cake在这里很聪明,现在可以为正常的请求和JSON/XML等请求提供不同的视图,如果需要,您可以灵活地返回这些结果。您现在应该能够通过以下方式访问控制器中的操作:使用URI /controller/action(它将使用/view/controller/action.ctp中的视图),或者使用URI /controller/action。json(它将使用/视图/控制器/json/action.ctp)
  2. If you don't want to define those views i.e. you don't need to do any further processing, and the response is ready to go, you can tell CakePHP to ignore the views and return the data immediately using _serialize. Using _serialize will tell Cake to format your response in the correct format (XML, JSON etc.), set the headers and return it as needed without you needing to do anything else (documentation). To take advantage of this magic:

    如果您不想定义这些视图,也就是说,您不需要进行任何进一步的处理,并且响应已经准备就绪,您可以告诉CakePHP忽略这些视图,并使用_serialize立即返回数据。使用_serialize将告诉Cake以正确的格式(XML、JSON等)格式化您的响应,设置标题并在需要时返回,而不需要做任何其他事情(文档)。利用这个魔法:

    • Set the variables you want to return as you would a view variable i.e. $this->set('post', $post);
    • 设置要返回的变量,就像设置视图变量一样,即$this->集合('post', $post);
    • Tell Cake to serialize it into XML, JSON etc. by calling $this->set('_serialize', array('posts'));, where the parameter is the view variable you just set in the previous line
    • 通过调用$this->set('_serialize', array('posts')),告诉Cake将其序列化为XML、JSON等;在这里,参数是您刚刚设置在前一行中的视图变量。

And that's it. All headers and responses will be taken over by Cake. This just leaves the JSONP to get working (documentation):

就是这样。所有标题和响应将由Cake接管。这让JSONP开始工作(文档):

  1. Tell Cake to consider the request a JSONP request by setting $this->set('_jsonp', true);, and Cake will go find the callback function name parameter, and format the response to work with that callback function name. Literally, setting that one parameter does all the work for you.
  2. 通过设置$this->set('_jsonp', true),告诉Cake考虑JSONP请求的请求;Cake将找到回调函数名参数,并格式化响应以使用回调函数名。实际上,设置一个参数就可以完成所有的工作。

So, assuming you've set up Cake to accept .json requests, this is what your typical action could look like to work with JSONP:

因此,假设您已经设置了Cake来接受.json请求,这就是您使用JSONP时的典型动作:

public function getTheFirstPost()

    $post = $this->Post->find('first');

    $this->set(array(
        'post' => $post,                 <-- Set the post in the view
        '_serialize' => array('post'),   <-- Tell cake to use that post
        '_jsonp' => true                 <-- And wrap it in the callback function
    )
);

And the JS:

JS:

$.ajax({
    url: "/controller/get-the-first-post.json",
    context: document.body,
    dataType: 'jsonp'
}).done(function (data) {
    console.log(data);
});

#2


5  

Ok, I found a solution on this site. Basically you override the afterFilter method with:

我在这个网站上找到了解决方案。基本上你用以下方法覆盖afterFilter方法:

public function afterFilter() {
    parent::afterFilter();

    if (empty($this->request->query['callback']) || $this->response->type() != 'application/json') {
        return;
    }

    // jsonp response
    App::uses('Sanitize', 'Utility');
    $callbackFuncName = Sanitize::clean($this->request->query['callback']);
    $out = $this->response->body();
    $out = sprintf("%s(%s)", $callbackFuncName, $out);
    $this->response->body($out);
}

I hope it helps someone else as well.

我希望它也能帮助别人。

#3


0  

For CakePHP 2.4 and above, you can do this instead.

对于CakePHP 2.4和以上版本,您可以这样做。

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

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

So you can simply write:

你可以这样写:

$this->set('_jsonp', true);

in the relevant action.

在相关的行动。

Or you can simply write:

或者你可以简单地写:

/**
 *
 * beforeRender method
 *
 * @return void
 */
    public function beforeRender() {
        parent::beforeRender();
        $this->set('_jsonp', true);
    }