【问题标题】:Laravel: how to avoid json on internal api callLaravel:如何在内部 api 调用中避免 json
【发布时间】:2013-12-21 20:15:37
【问题描述】:

Laravel 4:在 consume-your-own-api 的上下文中,我的 XyzController 使用我的自定义 InternalAPiDispatcher 类创建一个 Request 对象,将其推送到堆栈上(根据 this consideration),然后调度路由:

class  InternalApiDispatcher {
// ...
public function dispatch($resource, $method)
{
    $this->request = \Request::create($this->apiBaseUrl . '/' . $resource, $method);
    $this->addRequestToStack($this->request);

    return \Route::dispatch($this->request);
}  

首先,我正在为一个集合开发一个基本的 GET,并且希望响应内容采用 Eloquent 模型的格式,或者任何准备好传递给视图的格式(可能是存储库的东西)稍后当我变得更高级时)。让框架创建一个 json 响应然后我将其解码回其他内容以在视图中显示它似乎效率低下。什么是一种简单/高效/优雅的方式来引导请求以我希望的格式返回响应,无论我在代码中的什么位置?

另外,我看过 this post 很多,虽然我在 BaseContorller 中处理查询字符串的东西(感谢 this answer to my previous question),但这一切似乎都变得太复杂了,我觉得我在树上迷路了。

编辑:以下内容是否相关(来自laravel.com/docs/templates)?

“通过在控制器上指定布局属性,将为您创建指定的视图,并且将是应该从动作返回的假定响应。”

【问题讨论】:

    标签: api request format laravel-4 response


    【解决方案1】:

    如果您愿意,请随意将其标记为 OT,但我建议您可能需要从不同的角度重新考虑您的问题。

    如果您正在“使用您自己的 API”,它是通过 HTTP 交付的,那么您应该坚持使用这种使用方法。

    尽管看起来很奇怪,但好处是您实际上可以将应用程序的这一部分完全替换为其他服务器。您可以在不同的盒子上运行应用程序的不同部分,可以完全重写 HTTP 部分等等。“网络规模”的所有好处。

    您要走的路线是耦合发布者和订阅者。现在,因为他们都是你,或者更准确地说是你的单个应用程序,这不一定是一件坏事。但是,如果您想要能够在不诉诸 HTTP(或至少“类似 HTTP”)请求的情况下访问自己的“东西”的好处,那么我不会费心去伪造它。您最好定义一个不同的内部非网络服务 API,然后调用它。

    此服务可能是您的“Web api”的基础,实际上整个 HTTP 部分可能是核心服务之上的一个相当薄的控制器层。

    它距离你现在所在的位置还不到一百万英里,但与其采用旨在输出 HTTP 请求的东西并对其进行修改,不如制作一些可以输出对象的东西,并将其包装为 HTTP。

    【讨论】:

    • 这是我需要的那种大局观的帮助。虽然我已经用配置标志解决了我最初的问题,但整体结构似乎是错误的。但是让我看看我现在有没有。应用程序目录中的 ctrlrs、模型、视图等将管理我的应用程序的 UI,它仍然可以具有 RESTful url,并且这些 ctrlrs 可以调用内部服务 api,它将具有匹配的 RESTful url,并且可以作为基础单独的网络 API。但现在我发现自己置身于一堆命名空间中。你能给我提供一个适当目录结构的草图吗?谢谢。
    【解决方案2】:

    这是我解决问题的方法,以便对我的 API 的内部请求没有 json 编码或解码。该解决方案还演示了在 API 层上使用路由模型绑定,以及 API 层对存储库的使用。这一切对我来说都很好。

    路线:

    Route::get('user/{id}/thing', array(
        'uses' => 'path\to\Namespace\UserController@thing',
        'as' => 'user.thing'));
    //...
    Route::group(['prefix' => 'api/v1'], function() 
    {
        Route::model('thing', 'Namespace\Thing');
        Route::model('user', 'Namespace\User'); 
    
        Route::get('user/{user}/thing', [
        'uses' => 'path\to\api\Namespace\UserController@thing',
        'as' => 'api.user.thing']);
    //...
    

    控制器:

    UI: UserController@thing
    public function thing()
    {
        $data = $this->dispatcher->dispatch('GET', “api/v1/user/1/thing”)
            ->getOriginalContent();  // dispatcher also sets config flag...
        // use $data in a view;
    }
    

    API:UserController@thing

    public function thing($user)
    {
        $rspns = $this->repo->thing($user);
    
        if ($this->isInternalCall()) { // refs config flag 
            return $rspns;
        }
        return Response::json([
        'error' => false,
        'thing' => $rspns->toArray()
    ], 200);
    

    回购:

    public function thing($user)
    {   
        return $user->thing;
    }
    

    【讨论】:

      【解决方案3】:

      这是我在 Laravel 5.1 中实现它的方法。它需要对控制器进行一些根本性的更改才能工作。

      不要使用return response()->make($data) 输出响应,而是使用return $data

      这允许使用App::make('apicontroller')->methodname() 从其他控制器调用控制器方法。返回将是对象/数组,而不是 JSON。

      要对外部 API 进行处理,您现有的路由保持不变。您可能需要一个中间件来对响应进行一些按摩。以下是 JSON 的驼峰式键名的基本示例。

      <?php
      namespace App\Http\Middleware;
      use Closure;
      class ResponseFormer
      {
          public function handle($request, Closure $next)
          {
              $response = $next($request);
              if($response->headers->get('content-type') == 'application/json')
              {
                  if (is_array($response->original)) {
                      $response->setContent(camelCaseKeys($response->original));
                  }
                  else if (is_object($response->original)) {
                      //laravel orm returns objects, it is a huge time saver to handle the case here
                      $response->setContent(camelCaseKeys($response->original->toArray()));
                  }
              }
              return $response;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-11-24
        • 1970-01-01
        • 1970-01-01
        • 2021-10-04
        • 1970-01-01
        • 1970-01-01
        • 2018-07-18
        • 1970-01-01
        • 2021-12-16
        相关资源
        最近更新 更多