代码之家  ›  专栏  ›  技术社区  ›  Mugluck

如何在Laravel 5.6中将第三方API数据转换为收集资源?

  •  2
  • Mugluck  · 技术社区  · 6 年前

    我一直在为我们的各种web应用程序创建一个干净的接口,我遇到了一个障碍,即laravel的api资源没有正确地将传入的json数组转换为laravel集合。

    我只需要一个资源就可以做到:

        namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\Resource;
    use App\Product;
    
    class ProductResource extends Resource
    {
        /**
         * Transform the resource into an array.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function toArray($request)
        {
            return [
                'name' => $this->resource['product']['name'],
                'description' => $this->resource['product']['description'],
                'price' => $this->resource['product']['rental_rate']['price']
            ];
    
            //return parent::toArray($request);
        }
    }
    

    打印此响应输出:

    {"name":"Arri Skypanel S60-C","description":"Arri Sky Panel S60-C 450w input with a 2000w tungsten equivalent & Combo Stand","price":"260.0"}
    

    然而,试图把这个单一的项目变成一个项目的集合是行不通的。

    有人知道我遗漏了什么吗?

    拉取api数据如下所示:

    namespace App;
    use GuzzleHttp\Exception\GuzzleException;
    use GuzzleHttp\Client;
    
    class ThirPartyAPI
    {
        private $url = 'https://api.third-party.com/api/v1/';
    
        public function pull($query, $additionalParams) {
            $client = new Client;
            $result = $client->get($this->url . $query . $additionalParams, [
                'headers' => [
                    'Content-Type' => 'application/json',
                    'X-AUTH-TOKEN' => env('CURRENT-AUTH-TOKEN'),
                    'X-SUBDOMAIN' => env('CURRENT-SUBDOMAIN')
                ]
            ]);
            $array = json_decode($result->getBody()->getContents(), true);
    
            return $array;
        }
    }
    

    api返回大量json数据。

    这是产品型号:

    public function getAllProducts() {
            try {
    
                $productData = [];  
                    $query = "/products?page=1&per_page=3&filtermode=active";
                    $additionalParams = "";
                    $productData = new ThirdPartyAPI;
                    $productData = $productData->pull($query, $additionalParams);
    
                    $productData = $productData['products'];    
    
            return ProductsResource::make($productData);
        } catch (\Exception $ex) {
            return $ex;
        } catch (\Throwable $ex) {
            return $ex;
        }
    
    } 
    

    现在我正在尝试将所有返回的数组转换为我可以控制的更多数组:

    namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\Resource;
    
    class ProductsResource extends Resource
    {
        /**
         * Transform the resource into an array.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function toArray($request)
        {
            return [
                'products' => $this->collection->mapInto(function($request) {
                   return[ 'name' => $this->resource['name'],
                           'description' => $this->resource['description'],
                           'price' => $this->resource['rental_rate']['price']
                    ];
                })
            ];
    
        }
    

    然而,var_转储数据只返回以下信息:

    object(App\Http\Resources\ProductsResource)[200]
      public 'resource' => 
        array (size=3)
          0 => 
            array (size=37)
              'id' => int 164
              'name' => string '10A Dimmer' (length=10)
              [Lots of data]
                  ...
              'sale_rates' => 
                array (size=0)
                  ...
          1 => .....
          [cont]
     public 'with' => 
        array (size=0)
          empty
      public 'additional' => 
        array (size=0)
          empty
    

    我在返回的json信息上尝试了各种形式的数据转换,除了错误和混乱的业务之外,没有很多结果。我对laravel如何处理api资源处理有点不清楚。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Mugluck    6 年前

    好吧,在对laravel的集合的“make”、“map into”和“map”方法进行了一些调查之后,我终于从这里得到了一个工作结果:

    $productData = ThirdPartyAPI;
    $productData = $productData->pull($query, $additionalParams);
    $productData = $productData['products'];
    
    $products = collect($productData)->map(function($row){
          return ProductsResource::make($row)->resolve();
    });
    var_dump($products);
    

    var_dump返回:

    object(Illuminate\Support\Collection)[228]
      protected 'items' => 
        array (size=3)
          0 => 
            array (size=3)
              'name' => string '10A Dimmer' (length=10)
              'description' => string '10amp Dimmer (Max 2.4k)' (length=23)
              'price' => string '5.0' (length=3)
          ....
            [And so on]
    

    返回的初始信息是多维数组。

    $returnedArray = array(
        ['array' => 1, 'name' => 'name', etc],
        ['array' => 2, 'name' => 'name, etc]
    );
    

    laravel的默认收集方法只将顶部数组转换为一个集合。为了能够通过资源模型正确地控制结果,我们必须将整个数组集转换为集合,这意味着我们必须遍历返回的数据,将其转换为laravel可以正确读取的数据。这就是map方法的作用。

    根据 docs map方法遍历集合并将每个值传递给给定的回调。回调可以自由修改项并返回它,从而形成一个新的修改项集合。

    make方法创建一个新的集合实例。我不知道resolve函数做什么,除了 docs 提到它“使用服务容器将给定的类或接口名称解析为其实例”。我想这意味着它能确保正确地通过课堂?

    不管怎样,我希望这对将来的人们有帮助。