本文經Viraj Khatavkar同行評審。感謝所有SitePoint的同行評審員,使SitePoint的內容達到最佳狀態!
如果您之前構建過API,我敢打賭您習慣於直接將數據作為響應輸出。如果操作正確,這可能不會造成危害,但有一些實際的替代方案可以幫助解決這個問題。
其中一個可用的解決方案是Fractal。它允許我們在將模型作為響應返回之前,為模型創建一個新的轉換層。它非常靈活,易於集成到任何應用程序或框架中。
關鍵要點
- PHP Fractal是一種解決方案,允許開發人員在將模型作為響應返回之前為其模型創建新的轉換層,從而使JSON數據更易於管理和保持一致性。
- Fractal靈活且易於集成到任何應用程序或框架中。它的工作原理是使用Transformer將復雜的數據結構轉換為更簡單的格式,並使用Serializer來格式化最終輸出。
- Fractal還允許在用戶請求時包含子資源(關係)到響應中,從而為數據呈現增加了另一層靈活性和控制。
- 使用Fractal可以通過一次性急切加載關係來優化查詢性能,從而解決了Eloquent延遲加載經常遇到的n 1問題。
安裝
我們將使用Laravel 5.3應用程序來構建示例並將Fractal包與其集成,因此請繼續使用安裝程序或通過Composer創建一個新的Laravel應用程序。
<code>laravel new demo</code>
或
<code>composer create-project laravel/laravel demo</code>
然後,在文件夾內,我們需要Fractal包。
<code>composer require league/fractal</code>
創建數據庫
我們的數據庫包含users和roles表。每個用戶都有一個角色,每個角色都有一個權限列表。
// app/User.php class User extends Authenticatable { protected $fillable = [ 'name', 'email', 'password', 'role_id', ]; protected $hidden = [ 'password', 'remember_token', ]; /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function role() { return $this->belongsTo(Role::class); } }
// app/Role.php class Role extends Model { protected $fillable = [ 'name', 'slug', 'permissions' ]; /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function users() { return $this->hasMany(User::class); } }
創建Transformer
我們將為每個模型創建一個Transformer。我們的UserTransformer類如下所示:
// app/Transformers/UserTransformer.php namespace App\Transformers; use App\User; use League\Fractal\TransformerAbstract; class UserTransformer extends TransformerAbstract { public function transform(User $user) { return [ 'name' => $user->name, 'email' => $user->email ]; } }
是的,創建Transformer就這麼簡單!它只是以開發人員可以管理的方式轉換數據,而不是留給ORM或存儲庫。
我們擴展TransformerAbstract類並定義transform方法,該方法將使用User實例調用。 RoleTransformer類也是如此。
namespace App\Transformers; use App\Role; use League\Fractal\TransformerAbstract; class RoleTransformer extends TransformerAbstract { public function transform(Role $role) { return [ 'name' => $role->name, 'slug' => $role->slug, 'permissions' => $role->permissions ]; } }
創建控制器
我們的控制器應該在將數據發送回用戶之前轉換數據。我們現在將處理UsersController類,暫時只定義index和show操作。
// app/Http/Controllers/UsersController.php class UsersController extends Controller { /** * @var Manager */ private $fractal; /** * @var UserTransformer */ private $userTransformer; function __construct(Manager $fractal, UserTransformer $userTransformer) { $this->fractal = $fractal; $this->userTransformer = $userTransformer; } public function index(Request $request) { $users = User::all(); // 从数据库获取用户 $users = new Collection($users, $this->userTransformer); // 创建资源集合转换器 $users = $this->fractal->createData($users); // 转换数据 return $users->toArray(); // 获取转换后的数据数组 } }
index操作將從數據庫查詢所有用戶,使用用戶列表和轉換器創建一個資源集合,然後執行實際的轉換過程。
{ "data": [ { "name": "Nyasia Keeling", "email": "crooks.maurice@example.net" }, { "name": "Laron Olson", "email": "helen55@example.com" }, { "name": "Prof. Fanny Dach III", "email": "edgardo13@example.net" }, { "name": "Athena Olson Sr.", "email": "halvorson.jules@example.com" } // ... ] }
當然,一次返回所有用戶是沒有意義的,我們應該為此實現分頁器。
分頁
Laravel傾向於簡化事情。我們可以像這樣實現分頁:
<code>laravel new demo</code>
但是為了使這與Fractal一起工作,我們可能需要添加一些代碼來轉換數據,然後再調用分頁器。
<code>composer create-project laravel/laravel demo</code>
第一步是從模型分頁數據。接下來,我們像以前一樣創建一個資源集合,然後在集合上設置分頁器。
Fractal為Laravel提供了一個分頁器適配器來轉換LengthAwarePaginator類,它還為Symfony和Zend提供了一個適配器。
<code>composer require league/fractal</code>
請注意,它為分頁詳細信息添加了額外的字段。您可以在文檔中閱讀更多關於分頁的信息。
包含子資源
現在我們已經熟悉了Fractal,是時候學習如何在用戶請求時包含子資源(關係)到響應中了。
我們可以請求包含額外資源到響應中,例如http://demo.vaprobash.dev/users?include=role。我們的轉換器可以自動檢測正在請求的內容並解析include參數。
// app/User.php class User extends Authenticatable { protected $fillable = [ 'name', 'email', 'password', 'role_id', ]; protected $hidden = [ 'password', 'remember_token', ]; /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function role() { return $this->belongsTo(Role::class); } }
$availableIncludes屬性告訴轉換器我們可能需要包含一些額外的數據到響應中。如果include查詢參數請求用戶角色,它將調用includeRole方法。
// app/Role.php class Role extends Model { protected $fillable = [ 'name', 'slug', 'permissions' ]; /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function users() { return $this->hasMany(User::class); } }
$this->fractal->parseIncludes行負責解析include查詢參數。如果我們請求用戶列表,我們應該看到類似這樣的內容:
// app/Transformers/UserTransformer.php namespace App\Transformers; use App\User; use League\Fractal\TransformerAbstract; class UserTransformer extends TransformerAbstract { public function transform(User $user) { return [ 'name' => $user->name, 'email' => $user->email ]; } }
如果每個用戶都有一個角色列表,我們可以將轉換器更改為如下所示:
namespace App\Transformers; use App\Role; use League\Fractal\TransformerAbstract; class RoleTransformer extends TransformerAbstract { public function transform(Role $role) { return [ 'name' => $role->name, 'slug' => $role->slug, 'permissions' => $role->permissions ]; } }
包含子資源時,我們可以使用點表示法來嵌套關係。假設每個角色都有一個存儲在單獨表中的權限列表,並且我們想列出具有其角色和權限的用戶。我們可以這樣做include=role.permissions。
有時,我們需要默認包含一些必要的關聯,例如地址關聯。我們可以通過在轉換器中使用$defaultIncludes屬性來實現。
// app/Http/Controllers/UsersController.php class UsersController extends Controller { /** * @var Manager */ private $fractal; /** * @var UserTransformer */ private $userTransformer; function __construct(Manager $fractal, UserTransformer $userTransformer) { $this->fractal = $fractal; $this->userTransformer = $userTransformer; } public function index(Request $request) { $users = User::all(); // 从数据库获取用户 $users = new Collection($users, $this->userTransformer); // 创建资源集合转换器 $users = $this->fractal->createData($users); // 转换数据 return $users->toArray(); // 获取转换后的数据数组 } }
我最喜歡Fractal包的一件事是能夠將參數傳遞給include參數。文檔中的一個很好的例子是按順序排列。我們可以將其應用到我們的示例中,如下所示:
{ "data": [ { "name": "Nyasia Keeling", "email": "crooks.maurice@example.net" }, { "name": "Laron Olson", "email": "helen55@example.com" }, { "name": "Prof. Fanny Dach III", "email": "edgardo13@example.net" }, { "name": "Athena Olson Sr.", "email": "halvorson.jules@example.com" } // ... ] }
這裡重要的部分是list($orderCol, $orderBy) = $paramBag->get('order') ?: ['created_at', 'desc'];,這將嘗試從用戶include獲取order參數,並將其應用於查詢構建器。
我們現在可以通過傳遞參數來按順序排列包含的用戶列表(/roles?include=users:order(name|asc))。您可以在文檔中閱讀更多關於包含資源的信息。
但是,如果用戶沒有任何關聯的角色會怎樣?它將停止並出現錯誤,因為它期望的是有效數據而不是null。讓我們從響應中刪除該關係,而不是顯示其null值。
<code>laravel new demo</code>
急切加載
因為Eloquent在訪問模型時會延遲加載模型,所以我們可能會遇到n 1問題。這可以通過一次性急切加載關係來解決,以優化查詢。
<code>composer create-project laravel/laravel demo</code>
這樣,在訪問模型關係時,我們將不會有任何額外的查詢。
結論
我在閱讀Phil Sturgeon撰寫的《構建你不會討厭的API》時偶然發現了Fractal,這是一本很棒且內容豐富的讀物,我強烈推薦。
您在構建API時是否使用過轉換器?您是否有任何首選的執行相同工作的包,或者您只是使用json_encode?請在下面的評論部分告訴我們!
PHP Fractal常見問題解答
什麼是PHP Fractal,為什麼它很重要?
PHP Fractal是一個強大的工具,有助於為API呈現和轉換數據。它很重要,因為它提供了一種標準化的方法來輸出複雜、嵌套的數據結構,確保API的數據輸出一致、結構良好且易於理解。這使得開發人員更容易使用您的API,並減少了出錯的可能性。
PHP Fractal是如何工作的?
PHP Fractal的工作原理是獲取複雜的數據結構並將其轉換為更易於使用的格式。它通過兩個主要組件來實現:Transformer和Serializer。 Transformer負責將復雜的數據轉換為更簡單的格式,而Serializer則格式化最終輸出。
PHP Fractal中的Transformer是什麼?
PHP Fractal中的Transformer是定義應用程序數據應如何在API響應中輸出的類。它們獲取複雜的數據結構並將它們轉換為更簡單、更易於使用的格式。這允許您精確控制API響應中包含哪些數據以及數據的結構。
PHP Fractal中的Serializer是什麼?
PHP Fractal中的Serializer負責格式化API的最終輸出。它們獲取已由Transformer轉換的數據,並將其格式化為特定的結構。這允許您確保API的輸出一致且易於理解。
我如何在項目中實現PHP Fractal?
在項目中實現PHP Fractal包括通過Composer安裝Fractal庫,為數據創建Transformer,然後使用Fractal類使用Transformer轉換數據。然後,您可以使用Fractal的Serializer之一輸出轉換後的數據。
我可以將PHP Fractal與任何PHP項目一起使用嗎?
是的,PHP Fractal是一個獨立的庫,可以與任何PHP項目一起使用。它不依賴於任何特定的框架或平台,這使得它成為任何PHP開發人員的通用工具。
使用PHP Fractal的好處是什麼?
使用PHP Fractal提供了許多好處。它確保API的輸出一致且結構良好,使開發人員更容易使用。它還提供了一種標準化的方法來轉換複雜的數據結構,減少了出錯的可能性,並使代碼更容易維護。
PHP Fractal與其他數據轉換工具相比如何?
PHP Fractal以其簡單性和靈活性而脫穎而出。它提供了一種直接的方法來轉換複雜的數據結構,並且它使用Transformer和Serializer允許高度定制。這使得它成為任何使用API的開發人員的強大工具。
我可以自定義PHP Fractal的輸出嗎?
是的,PHP Fractal是高度可定制的。您可以創建自定義Transformer來精確控制數據的轉換方式,並且您可以使用不同的Serializer以不同的方式格式化輸出。這允許您根據您的特定需求調整API的輸出。
我在哪裡可以了解更多關於PHP Fractal的信息?
有很多資源可以幫助您了解更多關於PHP Fractal的信息。官方PHP League網站提供了全面的文檔,並且網上有許多教程和博文。此外,PHP Fractal GitHub存儲庫是一個探索代碼並查看其使用方法示例的好地方。
以上是PHP Fractal-使您的API json變得漂亮,永遠!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

TheSecretTokeEpingAphp-PowerEdwebSiterUnningSmoothlyShyunderHeavyLoadInVolvOLVOLVOLDEVERSALKEYSTRATICES:1)emplactopCodeCachingWithOpcachingWithOpCacheToreCescriptexecution Time,2)使用atabasequercachingCachingCachingWithRedataBasEndataBaseLeSendataBaseLoad,3)

你應該關心DependencyInjection(DI),因為它能讓你的代碼更清晰、更易維護。 1)DI通過解耦類,使其更模塊化,2)提高了測試的便捷性和代碼的靈活性,3)使用DI容器可以管理複雜的依賴關係,但要注意性能影響和循環依賴問題,4)最佳實踐是依賴於抽象接口,實現鬆散耦合。

是的,優化papplicationispossibleandessential.1)empartcachingingcachingusedapcutorediucedsatabaseload.2)優化的atabaseswithexing,高效Quereteries,and ConconnectionPooling.3)EnhanceCodeWithBuilt-unctions,避免使用,避免使用ingglobalalairaiables,並避免使用

theKeyStrategiestosigantificallyBoostPhpaPplicationPerformenCeare:1)UseOpCodeCachingLikeLikeLikeLikeLikeCacheToreDuceExecutiontime,2)優化AtabaseInteractionswithPreparedStateTementStatementStatementAndProperIndexing,3)配置

aphpdepentioncontiveContainerIsatoolThatManagesClassDeptions,增強codemodocultion,可驗證性和Maintainability.itactsasaceCentralHubForeatingingIndections,因此reducingTightCightTightCoupOulplingIndeSingantInting。

選擇DependencyInjection(DI)用於大型應用,ServiceLocator適合小型項目或原型。 1)DI通過構造函數注入依賴,提高代碼的測試性和模塊化。 2)ServiceLocator通過中心註冊獲取服務,方便但可能導致代碼耦合度增加。

phpapplicationscanbeoptimizedForsPeedAndeffificeby:1)啟用cacheInphp.ini,2)使用preparedStatatementSwithPdoforDatabasequesies,3)3)替換loopswitharray_filtaray_filteraray_maparray_mapfordataprocrocessing,4)conformentnginxasaseproxy,5)

phpemailvalidation invoLvesthreesteps:1)格式化進行regulareXpressecthemailFormat; 2)dnsvalidationtoshethedomainhasavalidmxrecord; 3)


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Atom編輯器mac版下載
最受歡迎的的開源編輯器

記事本++7.3.1
好用且免費的程式碼編輯器