الانتقال للمحتوى الرئيسي

بناء تطبيق ويب كامل باستخدام 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) @endforeach
العنوان الحالة الأولوية تاريخ الاستحقاق الفئة الإجراءات
{{ $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 عرض تعديل
@csrf @method('DELETE')
{{ $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
المستوى: متقدم