как бороться с запросом jsonp в php с помощью Slim Framework?

0

когда я отправляю запрос jsonp GET с помощью jQuery, он обычно отправляет что-то вроде:

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 Framework у меня есть:

$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

любые идеи, как я могу работать?

Теги:
slim
zend-framework
jsonp

4 ответа

0
Лучший ответ

Здесь есть несколько вещей. Во-первых, вы не должны получать 404, вы должны получить сообщение об ошибке, что $ resp не определен.

Я думаю, что вам, вероятно, не хватает.htaccess (или web.config, если вы работаете в IIS), который направляет все запросы в файл вашего фронтального контроллера (где вы определяете свой объект Slim и маршруты). Чтобы убедиться, что это проблема, попробуйте 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();

Я не на 100% знаком с Zend, но я думаю, что он использует более традиционную реализацию MVC, где у вас есть класс Controller, который вы расширяете и реализуете действия как методы. Slim намного более простой, чем это, вместо этого вы определяете маршруты на своих объектах приложения и сопоставляете их с закрытием, которые выполняются при ударе по их маршруту.

В моем примере выше я определяю закрытие маршрута '/test'. Закрытие в PHP не имеет доступа по умолчанию к другим переменным в их объеме. Чтобы получить доступ к переменной за пределами области закрытия, мы должны явно указать переменные, которые мы хотим, используя ключевое слово "use". В примере я "использую" объект $ app, так что мы можем использовать объект приложения внутри нашего закрытия. Это является основой для большинства функций, предоставляемых Slim. Объект $ app - это объект IOC, ядро, где все живет и должно использоваться для раскрытия объектов службы и т.д. В этом случае мы используем метод request(), который возвращает нам оболочку вокруг суперглобалов, связанных с запросами ($ _GET, $ _POST и т.д.).

Когда у нас есть наш параметр обратного вызова, мы можем проверить, а затем сгенерировать и отправить наш JSONP. Slim не абстрагирует (насколько я знаю) отправку данных обратно по отклику, вы должны просто использовать эхо, как в ванильном PHP. Вы также должны задать тип заголовка javascript, так как это то, что мы отправляем. Надеюсь это поможет.

  • 0
    я бы предпочел метод, использующий $app->response->setBody() , я не хотел бы использовать header('Content-type: text/javascript'); потому что это может быть не то, что мне нужно
  • 0
    Ответ @ Steve_ о переписывании пропущенного URL должен позаботиться о ваших 404 (дополнительную информацию см. В Slim docs: docs.slimframework.com/#Route-URL-Rewriting ). Если вы ищете «тонкий» стиль создания ответа, посмотрите пример здесь: github.com/jeremykendall/query-auth-impl/blob/master/public/… .
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;
});
0

Я наткнулся на этот ответ, пытаясь поддержать ответы JSONP в Slim v3.

Ответ от @cardeol не совсем поддержал мои потребности, так как некоторые из моих предыдущих вызовов промежуточного программного обеспечения использовали "$response-> withJson ($ data, $ code);

Этот вызов уничтожает и воссоздает объект тела. Промывка любого "ПЕРЕД" записывается.

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());

0

Вы раньше работали с 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

Обратите внимание, что нет необходимости в уродливом ?param=value в zend. просто добавьте его в URI с param/value

Примечание (важно): Есть $this->_helper->json($response) способа в zend для вывода json, поэтому $this->_helper->json($response) может быть не лучшим решением для вас. Использование contextSwitch внутри вашей функции init() может быть лучше.

  • 0
    моя проблема с Slim Framework, у меня есть Zend под контролем. Спасибо
  • 0
    извините - совершенно неправильно понял ваш вопрос!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню