Loading
Home About Services Portfolio Blog Community Contact Login Register عربي Hire Me
Back to Blog
Backend

Building a Professional RESTful API with Laravel 12

18 Apr 2026 8 472 views

يُعدّ بناء 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.

React to this article:

Comments

No comments yet. Be the first!

Login required to comment

Join the community and share your thoughts on articles

Share Article

All Articles
🤖

AI Assistant

Ask me about Mahmoud Nasr

Hi! I'm the AI assistant for Mahmoud Nasr. Ask me about his skills, experience, or projects! 👋
🗑️

Confirm Delete