API Resources در لاراول
قبل از نسخه لاراول 5.4 برای توسعه API در لاراول بهترین گزینه برای توسعه API در لاراول فرکتال بود.قبلا هر بار که یک پروژه جدید داشتم، اولین کاری که انجام می دادم نصب کردن فرکتال بود. واسه همین تنها چیزی که از لاراول انتظار داشتم تا در نسخه های جدیدش ارائه بده، رفع کردن همچین نیازی بود. قابلیت تبدیل داده ها برای ایجاد یک API بهتر.
حالا در در نسخه 5.5 لاراول Api resources قابلیت جدیدی که به لاراول اضافه شده، و ما رو از استفاده از کتابخانه ی دیگر بی نیاز کرده. فرکتال کتابخانه عالی هست، ولی من تا جایی که امکانش باشه ترجیح میدم که بیشترین استفاده رو از قابلیت های خود فریمورک بکنم.
API reources دقیقا مشابه فرکتال پیاده سازی شده، پس فهمیدن اینکه چطوری کار میکنه کار ساده ای حالا برای شروع یک مثال ساده با هم انجام می دیم.
قبل از اون هدف از استفاده از فرکتال یا Api resources در لاراول بگم:
- حذف داده های غیر ضرروی برای کاهش حجم خروجی
- مقادیر هر صفت رو بر اساس نوع آن برگشت بدیم. برای مثال اگه دارید صفت
price
رو برای یک محصول برمیگردونید به صورت رشته برنگردونیم! - قرار دادن روابط پیچیده (relationships) در خروجی
- پیاده سازی آسان pagination در داده ها
نصب لاراول 5.5
composer create-project laravel/laravel responses laravel-api
ایجاد جدول
Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->string('body'); $table->unsignedInteger('user_id'); $table->timestamps(); });
ایجاد یک resource با نام post
ریسورس ها در لاراول ویژگی جدیدی هستن که مدل ها و کالکشن مدل ها رو به راحتی برامون transform (تبدیل) میکنن. بزارید یک ریسورس برای مدل User درست کنیم:
php artisan make:resource User
بعد از اجرای دستور بالا، ریسورس User در مسیر app/Http/Resources
قرار میگیره.
مایگریشین users رو باز کنید و ستون هایی که دوست دارید رو بهش اضافه کنید:
public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->integer('telepone'); $table->string('photo'); $table->rememberToken(); $table->timestamps(); }); }
من اینجا ستون های telepone و photo رو اضافه کردم.
ویژگی جدید لاراول 5.5
خوب حالا چی؟
خوب، تا الان، ما یک مدل، کنترلر و مایگریشن داریم. و همینطور یک ریسورس که مدل و مدل کالشن ما رو به JSON تبدیل میکنه. خوب که چی؟
اول از همه، یک کلاس ریسورس چیه؟ کلاس User که توی دایرکتوری Resources ایجاد کردیم به چه دردی میخوره؟ خوب این کلاس متعلق به مدل User است و کارش فقط اینه که داده اون مدل رو به ساختار JSON تبدیل کنه.
بزارید کلاس User رو باز کنیم.
class User extends Resource { /** * Transform the resource into an array. * * @param \Illuminate\Http\Request * @return array */ public function toArray($request) { return parent::toArray($request); } }
خوب اینجا ما فقط یک متد به اسم toArray داریم که در حال حاضر آرایه ای از همه صفت هایی که مدل User داره رو برای تبدیل شدن به ساختار JSON برمیگردونه.
استفاده از ریسورس User
حال اجازه بدید بریم و از کنترلری که قبلا واسه User ایجاد کردیم برای برگردوندن اطلاعات یک کاربر بر اساس شناسه آن برگردونیم.
کنترلر User شما بعد از ایجاد تغییرات لازم باید به این صورت باشه:
<?php namespace App\Http\Controllers; use App\User; use App\Http\Resources\User as UserResource; class UserController extends Controller { public function show($id) { return new UserResource(User::findOrFail($id)); } }
برای ترنسفورم کردن اطلاعات کاربر، ما به سادگی مدل User رو به UserResource پاس میدیم.
خوب حال بزارید یک روت جدید واسه متد show بسازیم واسه اینکه نتیجه رو ببینیم.
روت api.php
رو باز کنید و کد زیر را اضافه کنید:
Route::get('/users/{id}', 'UserController@show');
حالا میتونید یک سیدر هم برای User اضافه کنید که یکسری داده فیک براش بسازید 🙂 بعد اینکار لینک زیر رو باز کنید.
http://laravelapi.dev/api/users/1
نتیجه ای که میبینید باید شبیه این باشه:
خوبس، حال اگه در داده بالا یکسری از صفت های مدل User مانند مثل updated_at
رو نخوایم نمایش بدیم چی؟ یا اینکه بخوایم برای خواناتر شدن اسم صفت photo
رو به avatar
تغییر بدیم. همچنین که مقدار مربوط به صفت photo را میبینید، آدرس تصویر کامل نیست و فاقد آدرس سرور هست.
پس ریسورس User رو دوباره باز کنید و داده برگشتی متد toArray رو به این صورت تغییر بدید:
public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'phone' => $this->telephone, 'avatar' => url($this->photo), 'registeredAt' => $this->created_at->toDateTimeString() ]; }
همونطور که میدونید اسم صفت telephone
رو موقع برگشت به phone
تغییر دادم. صفت های photo
به avatar
تغییر دادم همچنین آدرس سایت بهش اضافه کردم. بله، صفت updated_at
رو پاک کردم چون نیازی نبود که اون رو هم برگشت بدم. و در آخر هم created_at
به registeredAt
تغییر دادم.
اگه مرورگر رو رفرش کنیم نتیجه اینبار به این صورت میشه:
نکته مهمی که باید در نظر بگیرید اینه که همیشه مقادیر هر صفت رو بر اساس نوع آن برگشت داد. برای مثال اگه دارید صفت price
رو برای یک محصول برمیگردونید پس باید موقع برگشت دادنش تبدیلش کنید به نوع عدد. این باعث میشه که مقدار price
بعنوان رشته داخل کوتیشین قرار نگیره.
بزارید برای مثال در زیر صفت telephone
رو به عدد تبدیل کنیم:
public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'phone' => (int) $this->telephone, 'avatar' => url($this->photo), 'registeredAt' => $this->created_at->toDateTimeString() ]; }
اگه مرورگر رو دوباره رفرش کنید میبینید که مقدار صفت telephone به عدد تبدیل شده.
برای اطلاعات بیشتر در مورد API Resource این صفحه رو ی نگاهی بهش بندازید 😉