يُعدّ بناء RESTful API احترافي من أكثر المهارات طلبًا في سوق العمل الحديث. في هذا المقال سنبني معًا API متكامل لإدارة المهام (Task Manager) خطوة بخطوة، باستخدام أحدث إصدار من Laravel 12 مع تطبيق أفضل الممارسات في كل مرحلة.
01. إعداد المشروع
نبدأ بإنشاء مشروع Laravel جديد وتثبيت حزمة المصادقة:
# إنشاء مشروع جديد
composer create-project laravel/laravel task-api
cd task-api
# تثبيت Laravel Sanctum للمصادقة
composer require laravel/sanctum
php artisan install:api
02. إنشاء الـ Model والـ Migration
ننشئ الـ Task model مع الـ migration في أمر واحد:
php artisan make:model Task -mf
نكتب الـ migration:
public function up(): void
{
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title', 300);
$table->text('description')->nullable();
$table->enum('status', ['pending', 'in_progress', 'done'])->default('pending');
$table->date('due_date')->nullable();
$table->boolean('is_pinned')->default(false);
$table->timestamps();
});
}
والـ model الكامل:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Task extends Model
{
use HasFactory;
protected $fillable = [
'title', 'description', 'status',
'due_date', 'is_pinned', 'user_id',
];
protected function casts(): array
{
return [
'due_date' => 'date',
'is_pinned' => 'boolean',
];
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
03. بناء الـ API Resource Controller
php artisan make:controller Api/TaskController --api --model=Task namespace App\Http\Controllers\Api;
use App\Http\Requests\StoreTaskRequest;
use App\Http\Resources\TaskResource;
use App\Models\Task;
use Illuminate\Http\JsonResponse;
class TaskController extends Controller
{
public function index(): AnonymousResourceCollection
{
$tasks = auth()->user()->tasks()->latest()->paginate(15);
return TaskResource::collection($tasks);
}
public function store(StoreTaskRequest $request): TaskResource
{
$task = auth()->user()->tasks()->create($request->validated());
return new TaskResource($task);
}
public function show(Task $task): TaskResource
{
$this->authorize('view', $task);
return new TaskResource($task);
}
public function update(StoreTaskRequest $request, Task $task): TaskResource
{
$this->authorize('update', $task);
$task->update($request->validated());
return new TaskResource($task);
}
public function destroy(Task $task): JsonResponse
{
$this->authorize('delete', $task);
$task->delete();
return response()->json(['message' => 'Task deleted.'], 200);
}
}
04. API Resource — تنسيق الاستجابة
الـ API Resource يمنحك تحكمًا كاملًا في شكل البيانات المُرجَعة:
php artisan make:resource TaskResource class TaskResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'status' => $this->status,
'is_pinned' => $this->is_pinned,
'due_date' => $this->due_date?->format('Y-m-d'),
'created_at' => $this->created_at?->toISOString(),
];
}
}
الاستجابة النهائية:
{
"data": {
"id": 1,
"title": "إطلاق النسخة الجديدة من الموقع",
"status": "in_progress",
"is_pinned": true,
"due_date": "2025-05-01",
"created_at": "2025-04-18T10:30:00.000000Z"
}
}
05. Form Request — التحقق من البيانات
php artisan make:request StoreTaskRequest class StoreTaskRequest extends FormRequest
{
public function authorize(): bool { return true; }
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:300'],
'description' => ['nullable', 'string'],
'status' => ['nullable', 'in:pending,in_progress,done'],
'due_date' => ['nullable', 'date', 'after:today'],
'is_pinned' => ['boolean'],
];
}
public function messages(): array
{
return [
'title.required' => 'عنوان المهمة مطلوب.',
'due_date.after' => 'يجب أن يكون تاريخ الاستحقاق في المستقبل.',
'status.in' => 'الحالة: pending أو in_progress أو done.',
];
}
}
06. تعريف الـ Routes
// routes/api.php
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\TaskController;
// عامة
Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
// محمية بـ Sanctum
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('tasks', TaskController::class);
Route::post('logout', [AuthController::class, 'logout']);
});
📋 جدول الـ Endpoints
| Method | URI | Action | Auth |
|---|---|---|---|
| POST | /api/register | تسجيل مستخدم جديد | — |
| POST | /api/login | تسجيل الدخول والحصول على Token | — |
| GET | /api/tasks | جلب جميع المهام (paginated) | ✔ Bearer |
| POST | /api/tasks | إنشاء مهمة جديدة | ✔ Bearer |
| GET | /api/tasks/{id} | جلب مهمة محددة | ✔ Bearer |
| PUT | /api/tasks/{id} | تعديل مهمة | ✔ Bearer |
| DELETE | /api/tasks/{id} | حذف مهمة | ✔ Bearer |
07. المصادقة مع Laravel Sanctum
public function login(Request $request): JsonResponse
{
$request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if ( ! Auth::attempt($request->only('email', 'password'))) {
return response()->json([
'message' => 'بيانات الدخول غير صحيحة.',
], 401);
}
$user = Auth::user();
$token = $user->createToken('api-token')->plainTextToken;
return response()->json([
'token' => $token,
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
],
]);
}
08. معالجة الأخطاء في Laravel 12
// bootstrap/app.php
withExceptions(function (Exceptions $e) {
$e->render(function (NotFoundHttpException $ex, Request $request) {
if ($request->is('api/*')) {
return response()->json([
'message' => 'المورد المطلوب غير موجود.',
], 404);
}
});
$e->render(function (AuthorizationException $ex, Request $request) {
if ($request->is('api/*')) {
return response()->json([
'message' => 'غير مصرح لك بتنفيذ هذا الإجراء.',
], 403);
}
});
})
🚀 نصائح للإنتاج
- فعّل Rate Limiting على جميع الـ endpoints لحماية الخادم من الإساءة
- استخدم HTTPS دائمًا ولا ترسل الـ token عبر HTTP أبدًا
- طبّق API Versioning من اليوم الأول:
/api/v1/tasks - اربط Sentry أو Flare لمراقبة الأخطاء في الإنتاج
- اكتب Feature Tests لكل endpoint — الكود بدون اختبارات ليس جاهزًا للإنتاج
الآن لديك API كامل، آمن، قابل للتوسع، وجاهز للإنتاج 💪 في المقال القادم سنضيف Filtering وSorting وFull-Text Search على هذا الـ API.