使用CakePHP提供JSONP的正确方法是什么?

时间:2013-02-02 00:08:55

标签: cakephp jsonp

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

目前我可以通过关注CakePHP guide自动提供JSON内容。

3 个答案:

答案 0 :(得分:5)

好的,我找到了site的解决方案。基本上你用:

覆盖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);
}

我希望它也有助于其他人。

答案 1 :(得分:4)

我还没有找到如何正确使用CakePHP 2返回JSONP的完整示例,所以我要写下来。 OP要求正确的方法,但他的回答并没有使用2.4中现有的原生选项。对于2.4+,这是正确的方法,直接来自他们的文档:

  1. 设置您的视图以接受/使用JSON(documentation):

    • Router::parseExtensions('json');添加到您的routes.php配置文件中。这告诉Cake接受.json URI扩展
    • RequestHandler添加到您将要使用的控制器中的组件列表
    • Cake在这里变得聪明,现在为正常请求和JSON / XML等请求提供不同的视图,如果需要,您可以灵活地返回这些结果。您现在应该可以通过以下方式访问控制器中的操作:
      • 使用URI /controller/action(将使用/view/controller/action.ctp中的视图),或
      • 使用URI /controller/action.json(将使用/view/controller/json/action.ctp中的视图)
  2. 如果您不想定义这些视图,即您不需要进行任何进一步处理,并且响应已准备就绪,您可以告诉CakePHP忽略视图并立即使用返回数据_serialize。使用_serialize将告诉Cake以正确的格式(XML,JSON等)格式化您的响应,设置标题并根据需要返回它,而无需执行任何其他操作(documentation)。利用这种魔力:

    • 设置要返回的变量,就像设置视图变量$this->set('post', $post);
    • 一样
    • 告诉Cake通过调用$this->set('_serialize', array('posts'));将其序列化为XML,JSON等,其中参数是您在上一行中设置的视图变量
  3. 就是这样。所有标题和回复都将由Cake接管。这只是让JSONP开始工作(documentation):

    1. 告诉Cake通过设置$this->set('_jsonp', true);来考虑请求JSONP请求,并且Cake将找到回调函数名参数,并格式化响应以使用该回调函数名称。从字面上看,设置一个参数可以为您完成所有工作。
    2. 因此,假设您已设置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
          )
      );
      

      和JS:

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

答案 2 :(得分:0)

对于CakePHP 2.4及更高版本,您可以改为执行此操作。

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

所以你可以写一下:

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

在相关行动中。

或者您可以简单地写一下:

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