【问题标题】:Slim - How to send response with "Content-Type: application/json" header?Slim - 如何发送带有“Content-Type:application/json”标头的响应?
【发布时间】:2016-04-11 07:17:29
【问题描述】:

我有这个简单的 REST api,在 Slim 中完成,

<?php

require '../vendor/autoload.php';

function getDB()
{
    $dsn = 'sqlite:/home/branchito/personal-projects/slim3-REST/database.sqlite3';

    $options = array(
        PDO::ATTR_PERSISTENT => true,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    );
    try {

        $dbh = new PDO($dsn);

        foreach ($options as $k => $v)
            $dbh->setAttribute($k, $v);

        return $dbh;
    }
    catch (PDOException $e) {
        $error = $e->getMessage();
    }
}

$app = new \Slim\App();

$app->get('/', function($request, $response) {
    $response->write('Bienvenidos a Slim 3 API');
    return $response;
});

$app->get('/getScore/{id:\d+}', function($request, $response, $args) {

    try {
        $db = getDB();
        $stmt = $db->prepare("SELECT * FROM students
            WHERE student_id = :id
            ");

        $stmt->bindParam(':id', $args['id'], PDO::PARAM_INT);
        $stmt->execute();

        $student = $stmt->fetch(PDO::FETCH_OBJ);

        if($student) {
            $response->withHeader('Content-Type', 'application/json');
            $response->write(json_encode($student));

        } else { throw new PDOException('No records found');}

    } catch (PDOException $e) {

        $response->withStatus(404);
        $err =  '{"error": {"text": "'.$e->getMessage().'"}}';
        $response->write($err);
    }
    return $response;
});

$app->run();

但是,我无法让浏览器向我发送 application/json 内容类型,它 总是发送text/html?我做错了什么?

编辑:

好的,在头撞墙两个小时后,我偶然发现了这个答案:

https://github.com/slimphp/Slim/issues/1535(在页面底部) 这解释了会发生什么,似乎 response 对象是不可变的并且 因此,如果您想在之后退回它,则必须退回或重新分配 同时。

【问题讨论】:

  • 发送响应前是否设置了Content-Typehttp响应头?
  • ..你可以在我的代码中看到$response-&gt;withHeader('Content-Type', 'application/json');
  • 不应该是returnecho
  • 不。只需returnslimframework.com/docs

标签: php slim


【解决方案1】:

对于 V3,Slim docs 中最简单的方法是:

$data = array('name' => 'Rob', 'age' => 40);
return $response->withJson($data, 201);

这会自动将 Content-Type 设置为 application/json;charset=utf-8 并允许您设置 HTTP 状态代码(如果省略,则默认为 200)。

【讨论】:

    【解决方案2】:

    你也可以使用:

    $response = $response->withHeader('Content-Type', 'application/json');
    $response->write(json_encode($student));
    return $response;
    

    因为withHeader 返回新的响应对象。这样一来,您之间就有不止一个编写和代码。

    【讨论】:

      【解决方案3】:

      对于 V3,withJson() 可用。

      所以你可以这样做:

      return $response->withStatus(200)
                      ->withJson(array($request->getAttribute("route")
                      ->getArgument("someParameter")));
      

      注意:请务必返回$response,因为如果您忘记了,回复仍会出现,但不会是application/json

      【讨论】:

      • 为什么链在单独的行上不起作用?
      • @JomarSevillejo ,我需要查看您的代码以提供提示,但如果它们位于不同的行上,您仍然需要在这些行之后返回对象。
      • @jomar-sevillejo 这是因为 Response 对象是不可变的。每次你想“修改”它的一个属性时,实际上你所做的就是用这个属性的新值创建一个克隆。因此,链接有效,这是您必须返回给 Slim 的最后一个。
      • 添加:-&gt;withJson() 起作用的原因是它不仅设置了正文,还自动添加了标题Content-Type: application/json;charset=utf-8。正如其他人所指出的, Response 对象是不可变的,因此这将返回一个修改后的副本,然后必须由路由函数返回。
      【解决方案4】:

      所以,不要这样:

      if($student) {
                  $response->withHeader('Content-Type', 'application/json');
                  $response->write(json_encode($student));
                  return $response;
      
              } else { throw new PDOException('No records found');}
      

      这样做:

      if($student) {
          return $response->withStatus(200)
              ->withHeader('Content-Type', 'application/json')
              ->write(json_encode($student));
      
      } else { throw new PDOException('No records found');}
      

      一切都很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-08
        • 2011-09-07
        • 1970-01-01
        • 2017-08-25
        • 1970-01-01
        • 2013-02-10
        • 1970-01-01
        • 2019-03-08
        相关资源
        最近更新 更多