Laravel嵌套所有json响应

时间:2014-01-04 07:53:54

标签: php json rest laravel laravel-4

我正在使用Laravel创建一个JSON REST API,到目前为止它已经存在。但是我需要用一些由metaDataController(或者可能是模型)创建的元状态JSON来包装我的JSON输出,我很好奇这是一个很好的方法。

例如,所有回复都采用以下格式:

{
    "meta": {
        "status": 200, 
        "notifications": 2
    },
    "response": {
        //JSON from the route's Controller/Model/etc
    }
}

据我所知,我要么需要修改Laravel Response默认值并委托给metaDataController,要么创建某种Route::any来合并{{3}中提到的JSON的两个部分。 }}。虽然我总是知道metaDataController,但另一个控制器根据路径不断变化。

我认为必须有一种方法可以将此结构声明为所有路由或Route :: group的默认值。

谢谢!

2 个答案:

答案 0 :(得分:2)

我不认为做json_decode-> json_encode循环是一个可接受的解决方案(如Chris回答)。

这是另一种解决方案

use Illuminate\Http\Response;
use Illuminate\Http\Request;

Route::filter('apisuccess', function($route, Request $request, Response $response = null) {
    $response->setContent(json_encode([
        'data' => $response->original, 
        'meta' => ['somedata': 'value']
    ]));
});

然后我会将此过滤器附加到我的REST API路由。

编辑:另一种解决方案(更复杂)。

  1. 创建自定义Response类:
  2. use Illuminate\Http\Response;
    class ApiResponse extends Response
    {
        protected $meta;
        protected $data;
    
        public function __construct($content = '', $status = 200, $headers = array())
        {
            parent::__construct([], $status, $headers);
            $this->meta = [];
        }
    
        public function withMeta($property, $value = null)
        {
            if (is_array($property))
                $this->meta = $property;
            else 
                array_set($this->meta, $property, $value);
            return $this;
        }
    
        public function withData($data)
        {
            $this->data = $data;
            return $this;
        }
    
        public function sendContent()
        {
            echo json_encode(['success' => true, 'data' => $this->data, 'meta' => $this->meta, 'echo' => ob_get_contents()]);
        }
    }
    
    1. 将其作为IOC容器中的单例:

      $this->app->bindShared('ApiResponse', function() {
          return new \Truinject\Http\ApiResponse();
      });
      
    2. 最后,创建过滤器并将其用作"之前"在你的路线上:

    3. Route::filter('apiprepare', function(Illuminate\Routing\Route $route, Illuminate\Http\Request $request) {
          $data = $route->run();
          return App::make('ApiResponse')->withData($data);
      });
      

      因此我们基本上覆盖了我们自己的默认响应类,但仍然使用$ route-> run()调用适当的控制器来获取数据。

      要设置元数据,请在控制器中执行以下操作:

      \App::make('ApiResponse')->withMeta($property, $value);
      

      我添加了方法" meta"在我的基本API控制器类中,它封装了这个。

答案 1 :(得分:0)

您可以使用app.php中的全局后置过滤器来捕获所有回复,然后根据需要重新配置它:

App::after(function($request, $response)
{
    if(is_a($response, 'Illuminate\Http\JsonResponse')) {
        $response->setContent(json_encode(array(
            'data' => json_decode($response->getContent()),
            'foo' => 'bar',
            'cat' => 'dog'
        )));
    }
});

在上面的示例中,您将获取所有现有的json数据并将其放入子数据元素(在您的示例中这将是“响应”),然后添加foo和bar。所以foo,bar和data将是顶级json对象。

如果你不喜欢全球定位,after是一个发送的事件,所以你也可以在控制器/其他地方听它。