نحوه استفاده از API نسخه 3
این راهنما دستورالعملهای عملی برای کار با معماری Sun API v3 را ارائه میدهد، از جمله تولید کد، استفاده از کنترلر و پیادهسازی ترنسفورمر.
در این سند
تولید کد
API نسخه 3 با یک دستور آرتیزان مناسب برای تولید تمام اجزای لازم (کنترلر، ریپوزیتوری و ترنسفورمر) برای یک مدل خاص همراه است:
php artisan make:v3 "App\Modules\Shop\Entities\Order"
این دستور موارد زیر را ایجاد خواهد کرد:
- یک کنترلر در فضای نام مناسب
- یک ریپوزیتوری برای دسترسی به داده
- یک ترنسفورمر برای قالببندی پاسخ
کنترلر پایه
تمام کنترلرهای API باید از کلاس APIBaseController ارثبری کنند، که متدهای CRUD متعارف و سایر توابع کمکی را پیادهسازی میکند.
namespace App\Modules\Shop\Http\Controllers\V3;
use App\Http\Controllers\APIBaseController;
class OrderController extends APIBaseController
{
// متدهای سفارشی شما اینجا
}
متد لیست کلید-مقدار
یکی از متدهای مفید ارائه شده توسط APIBaseController، متد keyValList است که برای یکپارچهسازی با پلاگین جاوااسکریپت select2 طراحی شده است:
public function getOrderStatusOptions()
{
return $this->keyValList(
$this->repository->getStatusOptions(),
'id',
'name'
);
}
پیادهسازی ترنسفورمر
ترنسفورمرها بخش مهمی از معماری API نسخه 3 هستند. آنها دادههای شما را برای پاسخهای API قالببندی میکنند و روابط بین موجودیتها را مدیریت میکنند.
مثال: PostTransformer
در زیر یک مثال از ترنسفورمر برای موجودیت Post آورده شده است:
- ترنسفورمر کامل
- ویژگیهای پیکربندی
- متدهای Include
- متدهای فیلد اضافی
<?php
namespace App\Modules\CMS\Http\Transformers\V3\Client;
use App\Core\Comment\Http\Transformers\V3\Client\CommentTransformer;
use App\Core\Term\Http\Transformers\V3\Client\TermTransformer;
use App\Core\User\Http\Transformers\V3\Client\UserTransformer;
use App\Transformers\DateTimeTransformer;
use App\Modules\CMS\Entities\Post;
use App\Transformers\BaseTransformer;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
class PostTransformer extends BaseTransformer
{
protected array $additionalFields = [
'views',
];
protected array $blackListFields = [
'created_at',
'updated_at',
];
protected array $fieldsTransformer = [
'published_at'=> DateTimeTransformer::class,
];
protected array $availableIncludes = [
'comments',
'approved_comments',
];
protected array $defaultIncludes = [
'user',
'main_category',
'categories',
'tags'
];
public function includeUser(Post $post): Item
{
$user = $post->user;
return $this->item($user, new UserTransformer($this->request), 'user');
}
public function includeCategories(Post $post): Collection
{
$categories = $post->categories;
return $this->collection($categories, new TermTransformer($this->request), 'categories');
}
public function includeMainCategory(Post $post)
{
$category = $post->mainCategory()->first();
return is_null($category)
? $this->null() :
$this->item($category, new TermTransformer($this->request), 'mainCategory');
}
public function includeTags(Post $post): Collection
{
$tags = $post->tags;
return $this->collection($tags, new TermTransformer($this->request), 'tags');
}
public function includeComments(Post $post): Collection
{
$comments = $post->comments;
return $this->collection($comments, new CommentTransformer($this->request), 'comments');
}
public function includeApprovedComments(Post $post): Collection
{
$comments = $post->approvedComments;
return $this->collection($comments, new CommentTransformer($this->request), 'approvedComments');
}
public function addViews(Post $post)
{
return $post->views;
}
}
class PostTransformer extends BaseTransformer
{
// فیلدهایی که باید به پاسخ اضافه شوند که ویژگیهای مستقیم مدل نیستند
protected array $additionalFields = [
'views',
];
// فیلدهایی که باید از پاسخ حذف شوند
protected array $blackListFields = [
'created_at',
'updated_at',
];
// تعریف میکند که فیلدهای خاص چگونه باید تبدیل شوند
protected array $fieldsTransformer = [
'published_at'=> DateTimeTransformer::class,
];
// روابط اختیاری که میتوانند از طریق پارامترهای پرسوجو شامل شوند
protected array $availableIncludes = [
'comments',
'approved_comments',
];
// روابطی که همیشه در پاسخ گنجانده میشوند
protected array $defaultIncludes = [
'user',
'main_category',
'categories',
'tags'
];
// ... متدها ...
}
// رابطه تکی (Item برمیگرداند)
public function includeUser(Post $post): Item
{
$user = $post->user;
return $this->item($user, new UserTransformer($this->request), 'user');
}
// روابط چندگانه (Collection برمیگرداند)
public function includeCategories(Post $post): Collection
{
$categories = $post->categories;
return $this->collection($categories, new TermTransformer($this->request), 'categories');
}
// رابطهای که ممکن است null باشد
public function includeMainCategory(Post $post)
{
$category = $post->mainCategory()->first();
return is_null($category)
? $this->null() :
$this->item($category, new TermTransformer($this->request), 'mainCategory');
}
// متد برای اضافه کردن فیلدی که مستقیماً روی مدل نیست
public function addViews(Post $post)
{
return $post->views;
}
اجزای کلیدی ترنسفورمر
ویژگیهای پیکربندی
$additionalFields: فیلدهایی که باید به پاسخ اضافه شوند که ویژگیهای مستقیم مدل نیستند$blackListFields: فیلدهایی که باید از پاسخ حذف شوند$fieldsTransformer: تعریف میکند که فیلدهای خاص چگونه باید تبدیل شوند$availableIncludes: روابط اختیاری که میتوانند از طریق پارامترهای پرسوجو شامل شوند$defaultIncludes: روابطی که همیشه در پاسخ گنجانده میشوند
متدهای Include
برای هر رابطه، شما باید یک متد include{RelationName} ایجاد کنید که:
- مدل(های) مرتبط را بازیابی میکند
- آنها را با استفاده از ترنسفورمر مناسب تبدیل میکند
- آنها را به عنوان یک
Item(رابطه تکی) یاCollection(روابط چندگانه) برمیگرداند
متدهای فیلد اضافی
برای هر فیلد اضافی تعریف شده در $additionalFields، شما باید یک متد add{FieldName} ایجاد کنید که مقدار آن فیلد را برمیگرداند.
بهترین شیوهها
پیروی از این بهترین شیوهها به شما کمک میکند تا یک پیادهسازی API تمیز، کارآمد و سازگار را حفظ کنید.
- قراردادهای نامگذاری
- جداسازی دغدغهها
- استفاده مجدد از ترنسفورمرها
- بهینهسازی Includeها
- اشارههای نوع
1. نامگذاری سازگار
از قراردادهای نامگذاری برای کنترلرها، ریپوزیتوریها و ترنسفورمرها پیروی کنید:
App\Modules\{Module}\Http\Controllers\V3\{Audience}\{Resource}Controller
App\Modules\{Module}\Repositories\{Resource}Repository
App\Modules\{Module}\Http\Transformers\V3\{Audience}\{Resource}Transformer
2. جداسازی دغدغهها
- کنترلرها: درخواستها و پاسخهای HTTP را مدیریت میکنند
- ریپوزیتوریها: حاوی منطق کسبوکار و دسترسی به داده هستند
- ترنسفورمرها: داده را برای پاسخهای API قالببندی میکنند
// کنترلر - درخواست را مدیریت میکند
public function index(Request $request)
{
$posts = $this->repository->paginate();
return $this->response($posts);
}
// ریپوزیتوری - منطق کسبوکار را مدیریت میکند
public function getPublishedPosts()
{
return $this->model->where('status', 'published')->get();
}
// ترنسفورمر - ارائه را مدیریت میکند
public function transform(Post $post)
{
return [
'id' => $post->id,
'title' => $post->title,
// ...
];
}
3. استفاده مجدد از ترنسفورمرها
ترنسفورمرهای پایه برای موجودیتهای رایج ایجاد کنید و در صورت نیاز آنها را گسترش دهید:
// ترنسفورمر پایه
class BaseUserTransformer extends BaseTransformer
{
public function transform(User $user)
{
return [
'id' => $user->id,
'name' => $user->name,
// فیلدهای مشترک
];
}
}
// ترنسفورمر گسترش یافته
class AdminUserTransformer extends BaseUserTransformer
{
public function transform(User $user)
{
$data = parent::transform($user);
return array_merge($data, [
// فیلدهای مخصوص مدیر
'email' => $user->email,
'role' => $user->role,
]);
}
}
4. بهینهسازی Includeها
به روابطی که به طور پیشفرض در مقابل روابطی که در صورت نیاز شامل میشوند توجه کنید:
// تعداد زیادی include پیشفرض میتواند باعث مشکلات عملکردی شود
protected array $defaultIncludes = [
'user',
'category',
// فقط آنچه به طور پیشفرض مورد نیاز است را شامل کنید
];
// روابط سنگین را به صورت درخواستی در دسترس قرار دهید
protected array $availableIncludes = [
'comments',
'tags',
'relatedPosts',
// اینها را فقط در صورت درخواست شامل کنید
];
5. اشارههای نوع
همیشه از اشارههای نوع مناسب برای پارامترهای متد و انواع بازگشتی استفاده کنید:
// خوب
public function includeUser(Post $post): Item
{
$user = $post->user;
return $this->item($user, new UserTransformer($this->request), 'user');
}
// به خوبی نیست
public function includeUser($post)
{
$user = $post->user;
return $this->item($user, new UserTransformer($this->request), 'user');
}
با پیروی از این دستورالعملها، میتوانید به طور مؤثر از قدرت و انعطافپذیری معماری Sun API v3 بهرهمند شوید.