【问题标题】:how to deal with jsonp request in php using the Slim Framework?如何使用 Slim 框架处理 php 中的 jsonp 请求?
【发布时间】:2013-12-21 22:34:20
【问题描述】:

当我使用 jQuery 发送 jsonp GET 请求时,它通常会发送如下内容:

http://website.com/test?callback=jQuery20309569547907449305_1386221743664&id=9&limit=10&_=1386221743665

在 Zend Framework 中,我会这样处理:

$request  = $this->getRequest();
$callback = $request->getParam('callback');
$id       = $request->getParam('id');
$limit    = $request->getParam('limit');

// set $response var to something

$this->getResponse()->setBody($callback . '(' . json_encode($response) . ');');

在 Slim 框架中我有:

$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
$app->get(
    '/test',
    function () {
        $resp = array('This is a TEST route');
    }
);
$app->response->setBody($callback . '(' . json_encode($resp) . ');');

但是路由返回404

任何想法我怎样才能让它工作?

【问题讨论】:

    标签: php jquery zend-framework jsonp slim


    【解决方案1】:

    对于 Slim 3.x 只需在响应链中添加中间件

    $app->add(function ($request, $response, $next) { // jsonp
        $callback = $_GET['callback'] ?? false;
    
        if($callback) $response->getBody()->write($callback."(");
        $response = $next($request, $response);
        if($callback) $response->getBody()->write(")");
    
        return $response;
    });
    

    【讨论】:

      【解决方案2】:

      这里有几个问题。首先,你不应该得到 404,你应该得到一个错误,抱怨 $resp 没有定义。

      我认为您可能缺少将所有请求路由到前端控制器文件(在其中定义 Slim 对象和路由)的 .htaccess(或 web.config,如果您在 IIS 上)。要查看这是否是问题所在,请尝试http://website.com/index.php/test?callback=whatever,其中 index.php 是您的前端控制器文件的名称。

      这是我使用的 .htaccess:

      RewriteEngine On
      
      #Slim PHP routing
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_URI} !^/index.php
      RewriteRule ^ index.php [QSA,NC,L]
      

      至于试图达到你想要达到的目标,你需要这样的东西:

      $app = new Slim\Slim();
      
      $app->get('/test', function () use($app) {
      
          //Request processing begins here...
      
          //Get callback from query string
          $callback = $app->request()->get('callback');
      
          //Check for null here...
      
          //Set content type to javascript
          header('Content-type: text/javascript');
      
          //Generate our JSONP output
          echo "$callback(" . json_encode(array('This is a test.')) . ");";
      
          //Request processing ends here...
      
      });
      
      $app->run();
      

      我对 Zend 不是 100% 熟悉,但我认为它使用更传统的 MVC 实现,其中您有一个 Controller 类,您可以扩展和实现操作作为方法。 Slim 比这更基本,相反,您在应用对象上定义路由并将它们映射到闭包,当它们的路由被命中时执行。

      在上面的示例中,我为路由“/test”定义了一个闭包。默认情况下,PHP 中的闭包无法访问其范围内的其他变量。为了访问闭包范围之外的变量,我们必须通过“use”关键字明确指定我们想要的变量。在示例中,我“使用”了 $app 对象,以便我们可以在闭包中使用 app 对象。这是 Slim 提供的大部分功能的基础。 $app 对象是 IOC 对象,是一切存在的核心,应该用于公开服务对象等。在这种情况下,我们使用 request() 方法,该方法返回一个与请求相关的超全局变量($_GET , $_POST 等)。

      一旦我们有了回调参数,我们就可以验证,然后生成并发送我们的 JSONP。 Slim 不会抽象(据我所知)将数据发送回响应,您应该像在香草 PHP 中一样使用 echo。您还应该将标头类型设置为 javascript,因为这是我们发送的内容。希望这会有所帮助。

      【讨论】:

      【解决方案3】:

      你以前用过zend吗?我不太确定你是否知道 zend 是如何工作的。您没有任何带有回调的get() 函数,而是您有一个控制器(在您的情况下为:test)并且该控制器有几个操作。

      带有示例操作的文本控制器示例可能如下所示:

      class TestController extends Zend_Controller_Action
      {
      
          public function init()
          {
              //you might want to use here a contextSwitch 
          }
      
          public function fooAction()
          {
              //get params
              $limit = $this->_getParam('limit', 0);
              [...]
      
              //do stuff here
              [...]
      
              $this->_helper->json($response);
          }
      }
      

      您现在对该操作的调用可能如下所示:

      http://website.com/test/foo/limit/10

      请注意,zend 中不需要丑陋的?param=value。只需使用 param/value 将其附加到您的 URI

      注意(重要): zend 有多种输出json 的方法,因此$this->_helper->json($response) 可能不是最适合您的解决方案。在 init() 函数中使用 contextSwitch 可能会更好。

      【讨论】:

      • 我的问题是 Slim 框架,我已经控制了 zend。谢谢
      • 对不起 - 完全误解了你的问题!
      【解决方案4】:

      我在尝试支持 Slim v3 中的 JSONP 响应时遇到了这个答案。

      @cardeol 的回答并不能完全满足我的需求,因为我之前的一些中间件调用使用了“$response->withJson($data, $code);”

      此调用会销毁并重新创建 body 对象。刷新任何“BEFORE”写入。

      class JSONPResponseMiddleware {
      /**
       * Wrap response with callback query parameter
       *
       * @param  \Psr\Http\Message\ServerRequestInterface $request  PSR7 request
       * @param  \Psr\Http\Message\ResponseInterface      $response PSR7 response
       * @param  callable                                 $next     Next middleware
       *
       * @return \Psr\Http\Message\ResponseInterface
       */
      public function __invoke(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, $next){
          if(!$callback = $request->getQueryParam("callback", false)){
              return $next($request, $response);
          }
      
          $response = $next($request, $response);
          $data = $response->getBody();
      
          // upstream controllers use "withJSON" which purges the existing body object.
          $body = new Body(fopen('php://temp', 'r+'));
          $body->write("{$callback}(");
          $body->write($data);
          $body->write(")");
          $response = $response->withBody($body)->withHeader('Content-type', 'application/javascript');
          return $response;
      }
      

      }

      然后安装: $app->add(new JSONPResponseMiddleware());

      【讨论】:

        猜你喜欢
        • 2015-03-13
        • 2013-06-12
        • 1970-01-01
        • 1970-01-01
        • 2015-10-24
        • 2014-12-08
        • 1970-01-01
        • 1970-01-01
        • 2013-10-02
        相关资源
        最近更新 更多