国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

API 資源

API 資源


Eloquent: API 資源

簡介

當構建 API 時,你往往需要一個轉換層來聯(lián)結你的 Eloquent 模型和實際返回給用戶的 JSON 響應。Laravel 的資源類能夠讓你以更直觀簡便的方式將模型和模型集合轉化成 JSON。

生成資源

你可以使用 make:resource Artisan 命令來生成一個資源類。默認情況下生成的資源都會被放置在應用程序的 app/Http/Resources 文件夾下。資源繼承自 Illuminate\Http\Resources\Json\JsonResource 類:

php artisan make:resource User

資源集合

除了生成資源轉換單個模型外,你還可以生成資源集合用來轉換模型的集合。這允許你在響應中包含與給定資源相關的鏈接與其他元信息。

你需要在生成資源時添加 --collection 標志以生成一個資源集合?;蛘?,你也可以直接在資源的名稱中包含 Collection 向 Laravel 表示應該生成一個資源集合。資源集合繼承自 Illuminate\Http\Resources\Json\ResourceCollection 類:

php artisan make:resource Users --collection

php artisan make:resource UserCollection

概念綜述

{tip} 這是對資源和資源集合的高度概述。強烈建議你閱讀本文檔的其他部分,以深入了解如何更好地自定義和使用資源。

在深入了解如何定制化編寫你的資源之前,讓我們先來看看在 Laravel 中如何使用資源。一個資源類表示一個單一模型需要被轉換成 JSON 格式。例如,現(xiàn)在我們有一個簡單的 User 資源類:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\JsonResource;
    class User extends JsonResource{   
     /**
     * 將資源轉換成數(shù)組。
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */   
      public function toArray($request)  
        {      
          return [        
              'id' => $this->id,            
              'name' => $this->name,            
              'email' => $this->email,            
              'created_at' => $this->created_at,            
              'updated_at' => $this->updated_at,        
             ];   
         }
      }

每一個資源類都定義了一個 toArray 方法,在發(fā)送響應時它會返回應該被轉化成 JSON 的屬性數(shù)組。注意在這里我們可以直接使用 $this 變量來訪問模型屬性。這是因為資源類將自動代理屬性和方法到底層模型以方便訪問。你可以在路由或控制器中返回已定義的資源:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () {
    return new UserResource(User::find(1));
  });

資源集合

你可以在路由或者控制器中使用 collection 方法來創(chuàng)建資源實例,以返回多個資源的集合或分頁響應:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () { 
   return UserResource::collection(User::all());
  });

當然了,使用如上方法你將不能添加任何附加的元數(shù)據(jù)和集合一起返回。如果你需要自定義資源集合響應,你需要創(chuàng)建一個專用的資源來表示集合:

php artisan make:resource UserCollection

你可以輕松的在已生成的資源集合類中定義任何你想在響應中返回的元數(shù)據(jù):

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\ResourceCollection;
    class UserCollection extends ResourceCollection{ 
     /**
     * 將資源集合轉換成數(shù)組。
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */   
     public function toArray($request) 
        {       
         return [          
           'data' => $this->collection,            
           'links' => [           
                'self' => 'link-value',     
                  ],     
                ];   
           }
         }

你可以在路由或者控制器中返回已定義的資源集合:

use App\User;
use App\Http\Resources\UserCollection;
Route::get('/users', function () { 
   return new UserCollection(User::all());
  });

保護集合的鍵

當從路由返回資源集合時,Laravel 將重置集合的鍵,使它們以簡單的數(shù)字順序。但是,可以將 preserveKeys 屬性添加到資源類中,指示是否應保留集合鍵:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\JsonResource;
    class User extends JsonResource{  
      /**
     * 指示是否應保留資源的集合鍵。
     *
     * @var bool
     */    
   public $preserveKeys = true;
 }

preserveKeys 屬性被設置為 true, 集合的鍵將會被保護:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () {
    return UserResource::collection(User::all()->keyBy->id);
  });

自定義基礎資源類

通常,資源集合的 $this->collection 屬性會自動填充,結果是將集合的每個項映射到其單個資源類。假定單一資源類是集合的類名,但結尾沒有 Collection 字符串。

例如,UserCollection 將給定的用戶實例映射到 User 資源中。若要自定義此行為,你可以重寫資源集合的 $collects 屬性:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\ResourceCollection;
    class UserCollection extends ResourceCollection{  
      /**
     * collects 屬性定義了資源類。
     *
     * @var string
     */   
     public $collects = 'App\Http\Resources\Member';
    }

編寫資源

{tip} 如果你還沒有閱讀 概念綜述,那么在繼續(xù)閱讀本文檔前,強烈建議你去閱讀一下。

從本質上來說,資源的作用很簡單。它們只需要將一個給定的模型轉換成一個數(shù)組。所以每一個資源都包含一個 toArray 方法用來將你的模型屬性轉換成一個可以返回給用戶的 API 友好數(shù)組:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\JsonResource;
    class User extends JsonResource{  
      /**
     * 將資源轉換成數(shù)組。
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */   
      public function toArray($request) 
         {      
           return [          
             'id' => $this->id,            
             'name' => $this->name,            
             'email' => $this->email,            
             'created_at' => $this->created_at,            
             'updated_at' => $this->updated_at,     
             ];  
          }
       }

你可以在路由或者控制器中返回已經定義的資源:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () { 
   return new UserResource(User::find(1));
 });

關聯(lián)

如果你希望在響應中包含關聯(lián)資源,你只需要將它們添加到 toArray 方法返回的數(shù)組中。在下面這個例子里,我們將使用 Post 資源的 collection 方法將用戶的文章添加到資源響應中:

/**
 * 將資源轉換成數(shù)組。
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){ 
    return [    
        'id' => $this->id,        
        'name' => $this->name,        
        'email' => $this->email,        
        'posts' => PostResource::collection($this->posts),        
        'created_at' => $this->created_at,        
        'updated_at' => $this->updated_at,    
       ];
    }

{tip}  如果你只想在關聯(lián)已經加載時才添加關聯(lián)資源,請查看文檔 條件關聯(lián) 。

資源集合

資源是將單個模型轉換成數(shù)組,而資源集合是將多個模型的集合轉換成數(shù)組。所有的資源都提供了一個 collection 方法來生成一個 「臨時」 資源集合,所以你沒有必要為每一個模型類型都編寫一個資源集合類:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () {
    return UserResource::collection(User::all());
 });

不過,如果你需要自定義返回集合的元數(shù)據(jù),則仍需要定義一個資源集合:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\ResourceCollection;
    class UserCollection extends ResourceCollection{ 
    /**
     * 將資源集合轉換成數(shù)組
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */   
     public function toArray($request)   
      {     
         return [        
             'data' => $this->collection,            
             'links' => [           
                  'self' => 'link-value',     
                    ],       
                ];   
          }
     }

和單個資源一樣,你可以在路由或控制器中直接返回資源集合:

use App\User;
use App\Http\Resources\UserCollection;
Route::get('/users', function () {
    return new UserCollection(User::all());
  });

數(shù)據(jù)包裹

默認情況下,當資源響應被轉換成 JSON 時,頂層資源將會被包裹在 data 鍵中。因此一個典型的資源集合響應如下所示:

{    
    "data": [  
          {          
            "id": 1,            
            "name": "Eladio Schroeder Sr.",            
            "email": "therese28@example.com",       
           },       
           {           
            "id": 2,            
            "name": "Liliana Mayert",            
            "email": "evandervort@example.com",       
           }    
          ]
 }

你可以使用資源基類的 withoutWrapping 方法來禁用頂層資源的包裹。通常,你應該在  AppServiceProvider  或其他在程序每一個請求中都會被加載的 服務提供者 中調用此方法:

<?php
    namespace App\Providers;
    use Illuminate\Support\ServiceProvider;
    use Illuminate\Http\Resources\Json\Resource;
    class AppServiceProvider extends ServiceProvider{   
     /**
     * 在注冊后進行服務的啟動
     *
     * @return void
     */  
       public function boot()  
         {      
           Resource::withoutWrapping(); 
          }   
     /**
     * 在容器中注冊綁定
     *
     * @return void
     */  
      public function register()  
       {    
         //  
       }
    }

{note} withoutWrappin 方法只會禁用頂層資源的包裹,不會刪除你手動添加到資源集合中的 data 鍵。

包裹嵌套資源

你可以完全自由地決定資源關聯(lián)如何被包裹。如果你希望無論怎樣嵌套,都將所有資源集合包裹在 data 鍵中,那么你需要為每個資源都定義一個資源集合類,并將返回的集合包裹在 data 鍵中。

當然,你可能會擔心這樣頂層資源將會被包裹在兩個 data 鍵中。請放心, Laravel 將永遠不會讓你的資源被雙層包裹,因此你不必擔心被轉換的資源集合會被多重嵌套:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\ResourceCollection;
    class CommentsCollection extends ResourceCollection{  
      /**
     * 將資源集合轉換成數(shù)組
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */  
    public function toArray($request)  
      {      
        return ['data' => $this->collection]; 
      }
   }

數(shù)據(jù)包裹和分頁

當在資源響應中返回分頁集合時,即使你調用了 withoutWrapping 方法, Laravel 也會將你的資源數(shù)據(jù)包裹在 data 鍵中。這是因為分頁響應中總會有 metalinks 鍵包含著分頁狀態(tài)信息:

{  
  "data": [       
               {          
                 "id": 1,            
                 "name": "Eladio Schroeder Sr.",            
                 "email": "therese28@example.com",       
                 },        
                 {          
                   "id": 2,            
                   "name": "Liliana Mayert",            
                   "email": "evandervort@example.com",       
                 }    
               ],   
   "links":{     
           "first": "http://example.com/pagination?page=1",        
           "last": "http://example.com/pagination?page=1",        
           "prev": null,        
           "next": null  
          },    
    "meta":{      
      "current_page": 1,       
       "from": 1,        
       "last_page": 1,        
       "path": "http://example.com/pagination",        
       "per_page": 15,        
       "to": 10,        
       "total": 10    
      }
 }

分頁

你可以將分頁實例傳遞給資源的 collection 方法或者自定義的資源集合:

use App\User;
use App\Http\Resources\UserCollection;
Route::get('/users', function () {
    return new UserCollection(User::paginate());
  });

分頁響應中總有 metalinks 鍵包含著分頁狀態(tài)信息:

{  
  "data": [    
          {           
             "id": 1,            
             "name": "Eladio Schroeder Sr.",            
             "email": "therese28@example.com",      
          },        
          {          
            "id": 2,            
            "name": "Liliana Mayert",            
            "email": "evandervort@example.com",       
           }    
         ],   
    "links":{      
              "first": "http://example.com/pagination?page=1",        
              "last": "http://example.com/pagination?page=1",        
              "prev": null,        
              "next": null   
             },   
    "meta":{       
             "current_page": 1,       
             "from": 1,        
             "last_page": 1,        
             "path": "http://example.com/pagination",        
             "per_page": 15,        
             "to": 10,        
             "total": 10   
            }
}

條件屬性

有些時候,你可能希望在給定條件滿足時添加屬性到資源響應里。例如,你可能希望如果當前用戶是 「管理員」 時添加某個值到資源響應中。在這種情況下 Laravel 提供了一些輔助方法來幫助你解決問題。 when 方法可以被用來有條件地向資源響應添加屬性:

/**
 * 將資源轉換成數(shù)組
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){
     return [   
          'id' => $this->id,        
          'name' => $this->name,        
          'email' => $this->email,        
          'secret' => $this->when(Auth::user()->isAdmin(), 'secret-value'),        
          'created_at' => $this->created_at,        
          'updated_at' => $this->updated_at,  
          ];
      }

在上面這個例子中,只有當 isAdmin 方法返回 true 時, secret 鍵才會最終在資源響應中被返回。如果該方法返回 false ,則 secret 鍵將會在資源響應被發(fā)送給客戶端之前被刪除。 when 方法可以使你避免使用條件語句拼接數(shù)組,轉而用更優(yōu)雅的方式來編寫你的資源。

when 方法也接受閉包作為其第二個參數(shù),只有在給定條件為 true 時,才從閉包中計算返回的值:

'secret' => $this->when(Auth::user()->isAdmin(), function () {
    return 'secret-value';
  }),

有條件的合并數(shù)據(jù)

有些時候,你可能希望在給定條件滿足時添加多個屬性到資源響應里。在這種情況下,你可以使用 mergeWhen 方法在給定的條件為 true 時將多個屬性添加到響應中:

/**
 * 將資源轉換成數(shù)組
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){
     return [  
           'id' => $this->id,        
           'name' => $this->name,        
           'email' => $this->email,        
          $this->mergeWhen(Auth::user()->isAdmin(), [         
             'first-secret' => 'value',            
             'second-secret' => 'value',        
           ]),       
          'created_at' => $this->created_at,        
          'updated_at' => $this->updated_at,    
        ];
    }

同理,如果給定的條件為 false 時,則這些屬性將會在資源響應被發(fā)送給客戶端之前被移除。

{note} mergeWhen 方法不應該被使用在混合字符串和數(shù)字鍵的數(shù)組中。此外,它也不應該被使用在不按順序排列的數(shù)字鍵的數(shù)組中。

條件關聯(lián)

除了有條件地添加屬性之外,你還可以根據(jù)模型關聯(lián)是否已加載來有條件地在你的資源響應中包含關聯(lián)。這允許你在控制器中決定加載哪些模型關聯(lián),這樣你的資源可以在模型關聯(lián)被加載后才添加它們。

這樣做可以避免在你的資源中出現(xiàn) 「N+1」 查詢問題。你應該使用 whenLoaded 方法來有條件的加載關聯(lián)。為了避免加載不必要的關聯(lián),此方法接受關聯(lián)的名稱而不是關聯(lián)本身作為其參數(shù):

/**
 * 將資源轉換成數(shù)組
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){
     return [     
        'id' => $this->id,        
        'name' => $this->name,        
        'email' => $this->email,        
        'posts' => PostResource::collection($this->whenLoaded('posts')),        
        'created_at' => $this->created_at,        
        'updated_at' => $this->updated_at,  
         ];
    }

在上面這個例子中,如果關聯(lián)沒有被加載,則 posts 鍵將會在資源響應被發(fā)送給客戶端之前被刪除。

條件中間表信息

除了在你的資源響應中有條件地包含關聯(lián)外,你還可以使用 whenPivotLoaded  方法有條件地從多對多關聯(lián)的中間表中添加數(shù)據(jù)。 whenPivotLoaded 方法接受的第一個參數(shù)為中間表的名稱。第二個參數(shù)是一個閉包,它定義了在模型上如果中間表信息可用時要返回的值:

/**
 * 將資源轉換成數(shù)組
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){
     return [     
        'id' => $this->id,        
        'name' => $this->name,        
        'expires_at' => $this->whenPivotLoaded('role_user', function () {    
                return $this->pivot->expires_at;       
                 }),   
             ];
         }

如果你的中間表使用的是 pivot 以外的訪問器,你可以使用 whenPivotLoadedAs 方法:

/**
 * 將資源轉換成數(shù)組
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){
     return [   
          'id' => $this->id,        
          'name' => $this->name,        
          'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () { 
                     return $this->subscription->expires_at;       
                 }),    
            ];
       }

添加元數(shù)據(jù)

一些 JSON API 標準需要你在資源和資源集合響應中添加元數(shù)據(jù)。這通常包括資源或相關資源的 links ,或一些關于資源本身的元數(shù)據(jù)。如果你需要返回有關資源的其他元數(shù)據(jù),只需要將它們包含在 toArray 方法中即可。例如在轉換資源集合時你可能需要添加 links 信息:

/**
 * 將資源轉換成數(shù)組
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
 public function toArray($request){
     return [ 
            'data' => $this->collection,        
            'links' => [          
              'self' => 'link-value',      
              ],   
            ];
     }

當添加額外的元數(shù)據(jù)到你的資源中時,你不必擔心會覆蓋 Laravel 在返回分頁響應時自動添加的 linksmeta 鍵。你添加的任何其他 links 會與分頁響應添加的 links 相合并。

頂層元數(shù)據(jù)

有時候你可能希望當資源被作為頂層資源返回時添加某些元數(shù)據(jù)到資源響應中。這通常包括整個響應的元信息。你可以在資源類中添加 with 方法來定義元數(shù)據(jù)。此方法應返回一個元數(shù)據(jù)數(shù)組,當資源被作為頂層資源渲染時,這個數(shù)組將會被包含在資源響應中:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\ResourceCollection;
    class UserCollection extends ResourceCollection{   
       /**
     * 將資源集合轉換成數(shù)組
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */    
     public function toArray($request) 
        {      
          return parent::toArray($request);  
         }   
     /**
     * 返回應該和資源一起返回的其他數(shù)據(jù)數(shù)組
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */   
     public function with($request) 
        {    
            return [         
               'meta' => [                
               'key' => 'value',           
              ],      
             ];   
         }
     }

構造資源時添加元數(shù)據(jù)

你還可以在路由或者控制器中構造資源實例時添加頂層數(shù)據(jù)。所有資源都可以使用 additional 方法來接受應該被添加到資源響應中的數(shù)據(jù)數(shù)組:

return (new UserCollection(User::all()->load('roles')))       
         ->additional(['meta' => [             
                'key' => 'value',               
                 ]
              ]);

響應資源

就像你知道的那樣, 資源可以直接在路由和控制器中被返回:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () {
    return new UserResource(User::find(1));
 });

但有些時候,在發(fā)送給客戶端前你可能需要自定義 HTTP 響應。 你有兩種辦法。第一,你可以在鏈式上調用 response 方法。此方法將會返回  Illuminate\Http\Response 實例,允許你自定義響應頭信息:

use App\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () { 
   return (new UserResource(User::find(1)))         
          ->response()                
          ->header('X-Value', 'True');
        });

另外,你還可以在資源中定義一個 withResponse 方法。此方法將會在資源被作為頂層資源在響應時被調用:

<?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\JsonResource;
    class User extends JsonResource{   
     /**
     * 資源轉換成數(shù)組
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */   
      public function toArray($request)
          {      
            return [          
              'id' => $this->id,      
                ]; 
            }   
     /**
     * 自定義響應
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Http\Response  $response
     * @return void
     */  
     public function withResponse($request, $response)
         {     
            $response->header('X-Value', 'True'); 
         }
     }
本文章首發(fā)在 LearnKu.com 網站上。