بناء تطبيق ويب كامل باستخدام Laravel 10 - دليل شامل خطوة بخطوة
Laravel 10
Linux
متقدم
9091 مشاهدة
2025/12/07
دليل شامل لبناء تطبيق ويب كامل باستخدام Laravel 10
المقدمة
بناء تطبيق ويب كامل يتطلب فهماً شاملاً للعديد من المكونات. في هذا الدليل المفصل جداً، سنبني تطبيق إدارة المهام (Task Manager) باستخدام Laravel 10 مع شرح كل خطوة والمنطق وراءها.
ما سنبنيه:
- نظام إدارة المهام الكامل
- نظام مصادقة المستخدمين
- لوحة تحكم للمدراء
- واجهة برمجة تطبيقات (API)
- نظام إشعارات
- اختبارات تلقائية
المتطلبات:
- PHP 8.1 أو أحدث
- Composer
- Node.js و npm
- MySQL أو PostgreSQL
- Git
الخطوة 1: إعداد بيئة التطوير
تثبيت PHP و Composer:
تحقق من تثبيت PHP:
php --version
تحميل وتثبيت Composer:
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
تثبيت Node.js:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
إنشاء مشروع Laravel جديد:
composer create-project laravel/laravel taskmanager
cd taskmanager
إعداد ملف .env:
cp .env.example .env
php artisan key:generate
إعداد قاعدة البيانات:
قم بإنشاء قاعدة بيانات جديدة في MySQL:
mysql -u root -p
CREATE DATABASE taskmanager;
EXIT;
حدث ملف .env:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=taskmanager
DB_USERNAME=your_username
DB_PASSWORD=your_password
الخطوة 2: إعداد النماذج والجداول
إنشاء نموذج Task:
php artisan make:model Task -m
تعديل migration للمهام:
php artisan make:migration create_tasks_table
تعديل الملف database/migrations/xxxx_xx_xx_create_tasks_table.php:
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description')->nullable();
$table->enum('status', ['pending', 'in_progress', 'completed'])->default('pending');
$table->enum('priority', ['low', 'medium', 'high'])->default('medium');
$table->date('due_date')->nullable();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('assigned_to')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
});
}
إنشاء نموذج Category:
php artisan make:model Category -m
تعديل migration للفئات:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->string('color', 7)->default('#3498db');
$table->text('description')->nullable();
$table->timestamps();
});
ربط المهام بالفئات:
php artisan make:migration add_category_id_to_tasks_table --table=tasks
$table->foreignId('category_id')->nullable()->constrained()->onDelete('set null');
الخطوة 3: إعداد العلاقات في النماذج
تعديل نموذج User:
class User extends Authenticatable
{
public function tasks()
{
return $this->hasMany(Task::class);
}
public function assignedTasks()
{
return $this->hasMany(Task::class, 'assigned_to');
}
}
تعديل نموذج Task:
class Task extends Model
{
protected $fillable = [
'title', 'description', 'status', 'priority', 'due_date',
'user_id', 'assigned_to', 'category_id'
];
protected $casts = [
'due_date' => 'date',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function assignedUser()
{
return $this->belongsTo(User::class, 'assigned_to');
}
public function category()
{
return $this->belongsTo(Category::class);
}
}
تعديل نموذج Category:
class Category extends Model
{
protected $fillable = ['name', 'slug', 'color', 'description'];
public function tasks()
{
return $this->hasMany(Task::class);
}
protected static function boot()
{
parent::boot();
static::creating(function ($category) {
$category->slug = Str::slug($category->name);
});
static::updating(function ($category) {
$category->slug = Str::slug($category->name);
});
}
}
الخطوة 4: إنشاء Seeders للبيانات التجريبية
إنشاء CategorySeeder:
php artisan make:seeder CategorySeeder
Category::create([
'name' => 'العمل',
'color' => '#e74c3c',
'description' => 'مهام متعلقة بالعمل'
]);
Category::create([
'name' => 'الشخصي',
'color' => '#27ae60',
'description' => 'مهام شخصية'
]);
Category::create([
'name' => 'التعلم',
'color' => '#3498db',
'description' => 'مهام تعليمية'
]);
إنشاء TaskSeeder:
php artisan make:seeder TaskSeeder
$user = User::first();
Task::create([
'title' => 'إنهاء المشروع الأول',
'description' => 'يجب إنهاء المشروع الأول قبل الموعد المحدد',
'status' => 'in_progress',
'priority' => 'high',
'due_date' => now()->addDays(7),
'user_id' => $user->id,
'category_id' => 1
]);
الخطوة 5: إنشاء Controllers
إنشاء TaskController:
php artisan make:controller TaskController --resource
تعديل TaskController:
class TaskController extends Controller
{
public function index()
{
$tasks = auth()->user()->tasks()
->with('category', 'assignedUser')
->orderBy('created_at', 'desc')
->paginate(10);
return view('tasks.index', compact('tasks'));
}
public function create()
{
$categories = Category::all();
$users = User::all();
return view('tasks.create', compact('categories', 'users'));
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string',
'status' => 'required|in:pending,in_progress,completed',
'priority' => 'required|in:low,medium,high',
'due_date' => 'nullable|date|after:today',
'category_id' => 'required|exists:categories,id',
'assigned_to' => 'nullable|exists:users,id'
]);
$validated['user_id'] = auth()->id();
Task::create($validated);
return redirect()->route('tasks.index')
->with('success', 'تم إنشاء المهمة بنجاح');
}
public function show(Task $task)
{
$this->authorize('view', $task);
return view('tasks.show', compact('task'));
}
public function edit(Task $task)
{
$this->authorize('update', $task);
$categories = Category::all();
$users = User::all();
return view('tasks.edit', compact('task', 'categories', 'users'));
}
public function update(Request $request, Task $task)
{
$this->authorize('update', $task);
$validated = $request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string',
'status' => 'required|in:pending,in_progress,completed',
'priority' => 'required|in:low,medium,high',
'due_date' => 'nullable|date',
'category_id' => 'required|exists:categories,id',
'assigned_to' => 'nullable|exists:users,id'
]);
$task->update($validated);
return redirect()->route('tasks.index')
->with('success', 'تم تحديث المهمة بنجاح');
}
public function destroy(Task $task)
{
$this->authorize('delete', $task);
$task->delete();
return redirect()->route('tasks.index')
->with('success', 'تم حذف المهمة بنجاح');
}
}
الخطوة 6: إنشاء Policies للتحكم في الصلاحيات
إنشاء TaskPolicy:
php artisan make:policy TaskPolicy --model=Task
class TaskPolicy
{
public function view(User $user, Task $task)
{
return $user->id === $task->user_id || $user->id === $task->assigned_to;
}
public function update(User $user, Task $task)
{
return $user->id === $task->user_id;
}
public function delete(User $user, Task $task)
{
return $user->id === $task->user_id;
}
}
تسجيل Policy في AuthServiceProvider:
protected $policies = [
Task::class => TaskPolicy::class,
];
الخطوة 7: إنشاء Routes
تعديل routes/web.php:
Route::middleware('auth')->group(function () {
Route::resource('tasks', TaskController::class);
Route::get('/', [TaskController::class, 'index'])->name('home');
});
إنشاء API Routes:
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('api/tasks', TaskController::class);
});
الخطوة 8: إنشاء Views
إنشاء layout أساسي:
{{ config('app.name', 'Laravel') }}
@yield('content')
إنشاء صفحة قائمة المهام:
@extends('layouts.app')
@section('content')
المهام
إضافة مهمة جديدة
@if(session('success'))
{{ session('success') }}
@endif
العنوان
الحالة
الأولوية
تاريخ الاستحقاق
الفئة
الإجراءات
@foreach($tasks as $task)
{{ $task->title }}
{{ $task->status == 'completed' ? 'مكتملة' : ($task->status == 'in_progress' ? 'قيد التنفيذ' : 'معلقة') }}
{{ $task->priority == 'high' ? 'عالية' : ($task->priority == 'medium' ? 'متوسطة' : 'منخفضة') }}
{{ $task->due_date ? $task->due_date->format('Y-m-d') : 'غير محدد' }}
@if($task->category)
{{ $task->category->name }}
@endif
عرض
تعديل
@endforeach
{{ $tasks->links() }}
@endsection
الخطوة 9: إعداد Frontend مع Vite
تثبيت dependencies:
npm install
تثبيت Bootstrap و Vue.js:
npm install bootstrap @popperjs/core vue@next @vue/compiler-sfc
إعداد Vite لـ Vue:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: 'resources/js/app.js',
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
});
الخطوة 10: إنشاء Tests
إنشاء Feature Test:
php artisan make:test TaskTest
class TaskTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_create_task()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/tasks', [
'title' => 'Test Task',
'description' => 'Test Description',
'status' => 'pending',
'priority' => 'medium',
'category_id' => Category::factory()->create()->id
]);
$response->assertRedirect('/tasks');
$this->assertDatabaseHas('tasks', [
'title' => 'Test Task',
'user_id' => $user->id
]);
}
public function test_user_can_update_task()
{
$user = User::factory()->create();
$task = Task::factory()->create(['user_id' => $user->id]);
$response = $this->actingAs($user)->put("/tasks/{$task->id}", [
'title' => 'Updated Task',
'description' => 'Updated Description',
'status' => 'completed',
'priority' => 'high',
'category_id' => $task->category_id
]);
$response->assertRedirect('/tasks');
$this->assertDatabaseHas('tasks', [
'title' => 'Updated Task',
'status' => 'completed'
]);
}
}
تشغيل الاختبارات:
php artisan test
الخطوة 11: إعداد النشر
تحسين الأداء:
php artisan config:cache
php artisan route:cache
php artisan view:cache
بناء الأصول:
npm run build
إعداد .htaccess للنشر:
Options -MultiViews -Indexes
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
الخطوة 12: إعداد CI/CD مع GitHub Actions
إنشاء ملف workflow:
name: CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Copy Environment File
run: cp .env.ci .env
- name: Generate Application Key
run: php artisan key:generate
- name: Run Tests
run: php artisan test
خاتمة
تهانينا! لقد نجحت في بناء تطبيق ويب كامل باستخدام Laravel 10. التطبيق يتضمن جميع الميزات الأساسية لإدارة المهام مع نظام مصادقة، API، اختبارات، وإعدادات النشر.
الميزات المضافة:
- نظام مصادقة كامل
- إدارة المهام CRUD
- فئات المهام
- تعيين المهام للمستخدمين
- API للتطبيقات المحمولة
- اختبارات تلقائية
- نشر مع CI/CD
خطوات التطوير المستقبلية:
- إضافة نظام إشعارات
- تقارير وإحصائيات
- تطبيق محمول
- تكامل مع خدمات خارجية
- تحسين الأداء
من خلال
Mohannad Hassounah
مشرف
معلومات الشرح
البرنامج:
Laravel 10
نظام التشغيل:
Linux
المستوى:
متقدم