【问题标题】:Slim JSON Outputs苗条的 JSON 输出
【发布时间】:2011-10-12 01:16:08
【问题描述】:

我正在使用 Slim 框架和 PHP 来为我的应用程序创建一个 RESTful API。但是,我认为该框架将有某种方式来创建更简单的 JSON 输出,而不仅仅是 exit($jsonEncodedVariable);

我是否缺少框架中的某些内容,或者我是否需要为每种方法使用json_encode()...exit($json)...?

所有数据都从我的 MySQL 数据库中取出,然后根据调用的 REST 请求放入 JSON 数组中。

例如,如果请求/api/posts/all,我会exit() 一个包含所有帖子的 JSON 数组,每个帖子的值对应其自己的键 "value" : key

我的问题是,有没有一种简单的方法,使用 slim 框架,用于exit()'ing JSON 代码,而不是以纯文本形式退出?

【问题讨论】:

  • 请编辑您的问题,并提供有关您的问题的更多信息。很难从当前的请求中得到您的要求。
  • 已编辑。您需要更多信息吗?

标签: php json frameworks slim


【解决方案1】:

为什么不直接使用 Slim 的响应对象呢? (还有……为什么要退出?)

$dataAry = // Some data array

$response = $app->response();
$response['Content-Type'] = 'application/json';
$response['X-Powered-By'] = 'Potato Energy';
$response->status(200);
// etc.

$response->body(json_encode($dataAry));
// Or echo json_encode($dataAry)

让我先说我仍然认为自己是菜鸟,所以如果我犯了错误,请纠正我,以便我学习。但是,我正在处理一个类似的问题/问题,我想我可能会用 2 美分插话,并就此事进行更多讨论。关于 Slim on Stack 的信息越多越好。

我基本上是在玩同样的事情,我注意到你在使用 exit;起初,我使用 exit 也是因为 echo 包含一堆 HTML 并弄乱了返回给我的 AJAX 调用的内容。当我使用 exit 时,它干净利落地剪掉了 HTML,但是 Slim 响应对象并没有像我定义的那样更改响应标头(参见上面的代码。)

我意识到这并不是 Slim 的设计初衷。使用回声,而不是退出。注意 - Slim Doc:

每当您从路由回调中 echo() 内容时,echo() 的内容会被捕获 > 在输出缓冲区中,然后在 HTTP 响应 >返回给客户端之前附加到响应正文。

这很方便,但我无法回应。我搞砸的是一个更大的问题。内容与行为分离。如果您像我一样,您将设置一个单页应用程序,其中此代码基本上位于 index.php 上。我需要加载初始 html,因此我将其包含在该页面上。我需要做的是创造一个更干净的分离。我的路由设置正确,因此当人们 GET '/' Slim_Views(请参阅 Develop Rel.)为我返回渲染的 html 和 js 模板。太棒了!

现在我可以使用 Slim 的所有工具,而且我的代码更加简洁、独立、易于管理,并且更符合 http 协议。我想这就是框架的用途。 :-)

注意:我并不是说这一切都是你的结果,但我认为问题和你的设置看起来非常相似。它可能会帮助另一个在同一条道路上徘徊的新人。

更新:正如@alttag 提到的,这个答案已经过时了(Slim 2)

对于 Slim3,请参阅下面的答案或see this page in the documentation

【讨论】:

  • 嗯。我在这里找到了你的答案,并想试一试。退出看起来像是作弊......但是我不得不退出。我正在跨域发送我的请求并让 ajax 处理我在 echo json_data 后必须退出()的请求
  • 我实际上使用了您所说的解决方案,效果非常好。一些提示:如果您需要在 lambda 函数中使用 $app 变量,应将其添加到作用域 lihe this : function() use($app) {};或者您可以使用 \Slim\Slim::getInstance() 获取实例!
  • 或者,$app->response->headers->set('Content-Type', 'application/json');
  • 这是更好的答案。
  • 这是一个很好的 Slim2 答案。对于 Slim3,请参阅下面的答案或查看 this page in the documentation
【解决方案2】:
header("Content-Type: application/json");
echo json_encode($result);
exit;

提示:Using The Slim PHP Framework for Developing REST APIs

【讨论】:

  • IMO 这实际上应该被选为答案,因为它将正确的内容类型标头设置为响应的一部分。
  • 我不同意,orangewrap 的答案是通过响应对象而不是标头函数设置内容类型。任何一种方法都是有效的。为什么要退出?
  • 只因为你可以,不代表你需要。与往常一样,有很多方法可以实现所询问的内容,所以我不会说我在这里的答案比其他答案或多或少正确。
  • 我不同意,因为答案显示了自然的框架选项。我answered 举了一个使用正确选项来 Slim 的示例
  • 只是觉得在slimframework.com/docs/objects/response.html#returning-json 向其他访问者指向官方 Slim 文档会很好。因为我看到很多关于 SO 的问题都在询问如何实现这一点,这意味着这个问题及其答案可能仍然受到很多关注,并且由于这是一些人可能会依赖它的公认答案,这很好,因为它有效,但正如我现在所说的,Slim 提供了一种方法来简化这项任务。
【解决方案3】:

使用 Slim 3,我使用的是这种格式:

<?php

$app = new \Slim\App();

$app->get('/{id}', function ($request, $response, $args) {
    $id = $request->getAttribute('id');

    return $response->withJSON(
        ['id' => $id],
        200,
        JSON_UNESCAPED_UNICODE
    );
});

根据请求“/123”,结果 JSON 包含:

{
  id: "123"
}

更多信息read here.

[更新] 将第二个和第三个参数添加到 withJSON。二是HTTP状态码,三是Json编码选项(最适合特殊字符等,例如:正确打印“ã”)

【讨论】:

  • 是否有必要返回该对象?还是返回 void(不返回)就足够了,但其余部分如我们的示例所示?
  • 我不知道我是否理解你的评论@hakre,但是 Slim\Http\Response::withJson() 应该是 1 个参数。您可以发送一个字符串,例如“foo”,浏览器正文打印“foo”,标题为content-type:application/json。但通常情况下,您将此内容类型与 JSON 一起使用,因为我的返回是一个数组。
  • @hakre 在 Slim3 中必须返回修改后的$response,因为响应对象是不可变的。如果您不返回更新后的响应,则不会进行您的更改。
【解决方案4】:

您可以使用输出函数扩展 slim,其输出取决于调用的 REST 请求:

class mySlim extends Slim\Slim {
    function outputArray($data) {
        switch($this->request->headers->get('Accept')) {
            case 'application/json':
            default:
                $this->response->headers->set('Content-Type', 'application/json');
                echo json_encode($data);        
        }       
    } 
}

$app = new mySlim();

并像这样使用它:

$app->get('/test/', function() use ($app) {
    $data = array(1,2,3,4);
    $app->outputArray($data);
});

【讨论】:

    【解决方案5】:

    由于每个人都用函数和类来复杂化他们的答案,我将抛出这个简化的答案。 \Slim\Http\Response 可以像这样为你做到这一点:

    $app = new \Slim\Slim();
    
    $app->get('/something', function () use ($app) {
        $response = $app->response();
        $response['Content-Type'] = 'application/json';
        $response->status(200);
        $response->body(json_encode(['data' => []]));
    });
    
    $app->run();
    

    由于您很可能只返回 JSON 数据,因此制作适当的中间件可能是个好主意,请参阅 http://www.sitepoint.com/best-practices-rest-api-scratch-introduction/

    【讨论】:

      【解决方案6】:

      我认为 Slim 还提供了一个中间件对象,它会自动执行此操作,因此该框架的用户不必在每个请求上编写 json_decode 和编码,它称为 Slim_Middleware_ContentType 对象。

      $app->response()->('application/json');
      $app->add(new Slim_Middleware_ContentType());
      

      它会为您解码。解码效果很好。但是对于最后一篇文章的编码来说很棒。

      谢谢, 陀罗尼

      【讨论】:

      • 请注意这已经改变,现在是:$app-&gt;add(New \Slim\Middleware\ContentTypes());
      【解决方案7】:

      我感觉到你的痛苦。我想制作一个可重用的函数,所以我制作了一个帮助文件,并包含以下内容:

      function toJSON($app, $content) {
          $response = $app->response;
          $response['Content-Type'] = 'application/json';
          $response->body( json_encode($content) );
      };
      

      然后我像这样使用它:

      $app->get('/v1/users/:id', function($id) use ($app)
      {
          //instantiate SMM data model
          $model = new user_model($site);
      
          //get all docs, or one, depending on if query contains a page ID
          $doc = $model->get(array());
      
          //if the object contains main -- we don't need the outer data.
          toJSON($app, $doc);
      });
      

      编辑:我认为如果在流行的 mime 类型的响应对象中已经内置了这样的函数,那就太好了

      【讨论】:

        【解决方案8】:

        //JSON output in slim3
        
        $app->get('/users', function($request,$response,$args) {
        
            require 'db_connect.php';
        
            $stmt = $pdo->query("SELECT * FROM users");
            $result=$stmt->fetchAll(PDO::FETCH_ASSOC);
        
            if ($stmt->rowCount() > 0) {
                return $response->withStatus(200)
                        ->withHeader('Content-Type', 'application/json')
                        ->write(json_encode($result));
        
        
            }
            else{
                $result = array(
                    "status" => "false",
                    "message" => "Result not found"
                    );
                return $response->withStatus(200)
                        ->withHeader('Content-Type', 'application/json')
                        ->write(json_encode($result));
            }
        });
        

        【讨论】:

          【解决方案9】:
          function _die($array){
             echo json_encode($array);
             exit;
          }
          
          
          $result = mysql_query("SELECT * FROM table");
          while($row = mysql_fetch_assoc($result)){
              $array[] = $row;
          }
          
          _die($array);
          

          【讨论】:

          • 虽然我确实推荐了一些类似的东西,但我真的很希望看到你把它放在一个典型的苗条请求的背景下。
          【解决方案10】:

          为什么不用$response-&gt;write(json_encode($dataAry)); 而不是echo json_encode($dataAry);

          【讨论】:

          • 你需要把json放在header中
          【解决方案11】:

          我的解决方法是添加“exit;”在 json 打印结束时,我的开发服务器不在乎,但我的实时服务器不会触发 json 结束事件。我不需要添加标题或使用 json_encode。

          【讨论】:

            【解决方案12】:

            使用 Slim JSON API https://coderwall.com/p/otcphg/create-a-json-restfull-api-using-slim-framework。你可以用它处理 JSON 输出。

            【讨论】:

              【解决方案13】:

              [之前]:内容类型文本/html;字符集=UTF-8

              不适用于 SOAPUI JSON :(

              $this->get('get_all', function ($req, $res, $args) {
                  $um = new UserModel();
              
                  return $res
                     ->withHeader('Content-Type', 'application/json')
                     ->getBody()
                     ->write(
                      json_encode(
                          $um->get_all()
                      )
                  );
              });
              

              [之后]:Content-Type application/json;charset=utf-8

              使用 SOAPUI JSON ;)

              $this->get('get_all', function ($req, $res, $args) {
                  $um = new UserModel();
              
                  return $res
                      ->withHeader('Content-type', 'application/json;charset=utf-8')
                      ->withJson($um->get_all());
              

              【讨论】:

                【解决方案14】:

                可以在slim3中使用Slim的Response对象自定义方法withJson($data, $status, $encodingOptions)

                $app->get('/hello/{name}', function ($request, $response, $args) {
                    $data['msg']='Hello '.$request->getAttribute('name');
                    $newResponse = $response->withJson($data);
                });
                

                更多信息read here.

                【讨论】:

                  【解决方案15】:

                  这就是我在苗条版本 2 中的做法

                  $app->response->headers->set("Content-Type", 'application/json');
                  return $app->response->write(json_encode([
                      'status' => true,
                      'message' => 'Your message'
                  ]));
                  

                  【讨论】:

                    【解决方案16】:

                    我将https://github.com/entomb/slim-json-api 用于我用 Slim 2 编写的 API 以启用 JSON 响应。初始化代码如下所示:

                    function APIRequests () {
                        $app = \Slim\Slim::getInstance();
                        $app->view(new \JsonApiView());
                        $app->add(new \JsonApiMiddleware());
                    }
                    
                    $app->group('/api', 'APIRequests', function () use ($app) {
                        $app->get('/areas/:id', function ($id) use ($app) {
                           $app->render(200, Area::find($id));
                        });
                    });
                    

                    我非常喜欢使用中间件和路由分组的抽象级别,可以轻松地将不同的响应类型应用于应用程序的不同区域。

                    【讨论】:

                      【解决方案17】:

                      header("Content-Type : application/json"); echo json_encode($data);

                      【讨论】:

                        猜你喜欢
                        • 2020-05-13
                        • 1970-01-01
                        • 2013-07-22
                        • 2020-03-06
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2021-01-15
                        • 2017-06-24
                        相关资源
                        最近更新 更多