Seamless design · High performance
PHP · MVC · Routes · Controllers · Models · Migrations · Eloquent · Blade · CRUD · HTTP
مادة مرجعية منظّمة · أمثلة عملية · تمارين مع حلول
برمجة المواقع (Web Development) هي بناء تطبيقات تعمل عبر المتصفح أو تتفاعل مع الإنترنت. المستخدم يرى واجهة (صفحات، أزرار، نماذج)، بينما يعمل منطق التطبيق وتخزين البيانات في الخلفية على خادم (Server).
تنقسم عادةً إلى:
في هذه المحاضرة نركّز على Back-end باستخدام إطار العمل Laravel المبني على لغة PHP.
PHP لغة برمجة تُنفَّذ على الخادم. النتيجة غالبًا صفحة HTML أو JSON تُرسل للمتصفح. Laravel مكتوب بـ PHP، لذا فهم الأساسيات ضروري.
| المفهوم | الشرح |
|---|---|
$متغير | تخزين قيمة؛ يبدأ الاسم بعلامة $ |
array | مصفوفة/قائمة قيم |
function | كتلة قابلة لإعادة الاستخدام |
class | قالب لكائنات (OOP) |
if / foreach | شروط وحلقات تكرار |
require | تضمين ملف PHP آخر |
<?php
$name = "أحمد";
$age = 20;
function greet(string $name): string {
return "مرحباً، " . $name;
}
echo greet($name); // مرحباً، أحمد
$books = ["Laravel", "PHP", "MySQL"];
foreach ($books as $book) {
echo $book . "\n";
}
ملاحظة للطالب: في Laravel نادرًا ما نكتب <?php داخل ملفات Blade للمنطق المعقّد؛ نضع المنطق في Controller أو Model، ونستخدم Blade للعرض فقط.
Laravel إطار عمل (Framework) PHP حديث يسرّع بناء تطبيقات الويب عبر توفير:
تثبيت مشروع جديد (يتطلب Composer و PHP):
composer create-project laravel/laravel my-app
cd my-app
php artisan serve
ثم افتح المتصفح على http://127.0.0.1:8000.
MVC نمط تصميم يفصل المسؤوليات في تطبيق الويب:
| الطبقة | الدور في Laravel | مثال |
|---|---|---|
| Model | تمثيل البيانات والتعامل مع قاعدة البيانات | app/Models/Student.php |
| View | عرض البيانات للمستخدم (واجهة) | resources/views/students/index.blade.php |
| Controller | يستقبل الطلب، ينفّذ المنطق، يختار الـ View | app/Http/Controllers/StudentController.php |
flowchart LR
U[المستخدم / المتصفح] -->|HTTP Request| R[Routes]
R --> C[Controller]
C --> M[Model / Eloquent]
M --> DB[(MySQL)]
DB --> M
M --> C
C --> V[View / Blade]
V -->|HTTP Response| U
لماذا MVC؟ لتنظيم الكود: تعديل قاعدة البيانات لا يخلط مع HTML، وتغيير التصميم لا يكسر منطق الأعمال.
كل تفاعل على الويب يمر بهذه الدورة:
public/index.php ثم Routes ثم Controller.
sequenceDiagram
participant B as المتصفح (Client)
participant L as Laravel (Server)
participant D as MySQL (Database)
B->>L: Request GET /students
L->>D: SELECT * FROM students
D-->>L: صفوف البيانات
L-->>B: Response HTML (صفحة الطلاب)
HTTP بروتوكول نقل البيانات بين العميل والخادم. HTTPS هو HTTP مع تشفير SSL/TLS — ضروري للمواقع الحقيقية (كلمات مرور، بيانات حساسة).
| الطريقة | الغرض المعتاد | مثال CRUD |
|---|---|---|
GET | جلب/عرض بيانات دون تغيير | عرض قائمة أو صفحة تفاصيل |
POST | إرسال بيانات جديدة للإنشاء | Create — إضافة طالب |
PUT / PATCH | تحديث سجل موجود | Update — تعديل طالب |
DELETE | حذف سجل | Delete — حذف طالب |
في Laravel نربط كل طريقة بمسار:
// routes/web.php
Route::get('/students', [StudentController::class, 'index']); // Read (قائمة)
Route::get('/students/{id}', [StudentController::class, 'show']); // Read (واحد)
Route::post('/students', [StudentController::class, 'store']); // Create
Route::put('/students/{id}', [StudentController::class, 'update']); // Update
Route::delete('/students/{id}', [StudentController::class, 'destroy']); // Delete
في النماذج HTML، المتصفح يدعم GET و POST فقط؛ لـ PUT و DELETE نستخدم غالبًا @method('PUT') داخل نموذج POST.
MySQL نظام إدارة قواعد بيانات علائقية (RDBMS). Laravel لا يستبدل MySQL — بل يتصل به عبر إعدادات الاتصال ويترجم استعلامات Eloquent إلى SQL.
ماذا يفعل MySQL لـ Laravel؟
مثال جدول students:
| id | name | created_at | |
|---|---|---|---|
| 1 | سارة | sara@mail.com | 2025-01-10 |
| 2 | علي | ali@mail.com | 2025-01-11 |
Laravel يتصل عبر ملف config/database.php والقيم من .env.
ملف .env في جذر المشروع يحفظ إعدادات حساسة أو متغيرة حسب البيئة (تطوير / إنتاج). لا يُرفع عادةً إلى Git.
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:...
APP_DEBUG=true
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_app_db
DB_USERNAME=root
DB_PASSWORD=
php artisan أداة سطر أوامر Laravel. أهم الأوامر لهذه المادة:
| الأمر | الوظيفة |
|---|---|
php artisan serve | تشغيل خادم التطوير المحلي |
php artisan make:model Student | إنشاء Model |
php artisan make:controller StudentController | Controller جاهز لـ CRUD |
php artisan migrate | تنفيذ migrations وإنشاء/تحديث الجداول |
php artisan make:migration create_students_table | ملف migration جديد |
الـ Route يربط عنوان URL + طريقة HTTP بدالة في Controller (أو Closure).
// routes/web.php
use App\Http\Controllers\StudentController;
Route::get('/', function () {
return view('welcome');
});
Route::resource('students', StudentController::class);
// ينشئ تلقائياً: index, create, store, show, edit, update, destroy
Route::get('/students', [StudentController::class, 'index'])->name('students.index');
// في Blade:
// <a href="{{ route('students.index') }}">الطلاب</a>
الـ Controller يجمع منطق التطبيق: يقرأ الـ Request، يتعامل مع الـ Model، ويعيد View أو Redirect.
// app/Http/Controllers/StudentController.php
namespace App\Http\Controllers;
use App\Models\Student;
use Illuminate\Http\Request;
class StudentController extends Controller
{
public function index()
{
$students = Student::all();
return view('students.index')->with('students', $students);
}
public function store(Request $request)
{
$student = new Student();
$student->name = $request->name;
$student->email = $request->email;
$student->save();
return redirect()->route('students.index')->with('success', 'تمت الإضافة');
}
public function show($id)
{
$student = Student::find($id);
return view('students.show')->with('student', $student);
}
public function edit($id)
{
$student = Student::find($id);
return view('students.edit')->with('student', $student);
}
public function update(Request $request, $id)
{
$student = Student::find($id);
$student->name = $request->name;
$student->email = $request->email;
$student->save();
return redirect()->route('students.index')->with('success', 'تمت التحديث');
}
public function destroy(Student $student)
{
$student->delete();
return redirect()->route('students.index')->with('success', 'تمت الحذف');
}
}
الـ Model يمثّل جدولاً في قاعدة البيانات. Eloquent هو ORM في Laravel: تتعامل مع الصفوف ككائنات PHP بدل كتابة SQL يدوياً في كل مكان.
كل صف في الجدول = Entity (كيان)؛ والـ Model هو الفئة التي تمثّله.
// app/Models/Student.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
protected $fillable = ['name', 'email', 'department_id'];
// علاقة: طالب ينتمي لقسم
public function department()
{
return $this->belongsTo(Department::class);
}
}
Migration ملف PHP يصف بنية الجدول (الأعمدة والأنواع). يُنفَّذ بـ php artisan migrate فيُنشئ الجدول في MySQL. هذا يجعل بنية قاعدة البيانات قابلة للتتبع بـ Git مثل الكود.
// database/migrations/xxxx_create_students_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->foreignId('department_id')->constrained()->cascadeOnDelete();
$table->timestamps(); // created_at, updated_at
});
}
public function down(): void
{
Schema::dropIfExists('students');
}
};
ترتيب العمل المعتاد: Migration → migrate → Model → Controller → Routes → Views.
قواعد البيانات العلائقية تربط الجداول لتجنب تكرار البيانات.
مثال: كل مستخدم له ملف شخصي واحد.
// User.php
public function profile() {
return $this->hasOne(Profile::class);
}
// Profile.php
public function user() {
return $this->belongsTo(User::class);
}
مثال: قسم واحد يضم عدة طلاب.
// Department.php
public function students() {
return $this->hasMany(Student::class);
}
// Student.php
public function department() {
return $this->belongsTo(Department::class);
}
مثال: طلاب يسجّلون في عدة مواد، وكل مادة بها عدة طلاب. نحتاج جدول وسيط course_student.
// Student.php
public function courses() {
return $this->belongsToMany(Course::class);
}
// Course.php
public function students() {
return $this->belongsToMany(Student::class);
}
CRUD اختصار لأربع عمليات أساسية على أي مورد (مثل الطلاب):
| الحرف | العملية | HTTP | دالة Controller |
|---|---|---|---|
| C | Create — إنشاء | POST | store |
| R | Read — قراءة | GET | index, show |
| U | Update — تحديث | PUT/PATCH | update |
| D | Delete — حذف | DELETE | destroy |
Blade محرك القوالب في Laravel. يسمح بقالب رئيسي (Layout) وأقسام يملؤها كل صفحة.
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<title>@yield('title', 'تطبيقي')</title>
</head>
<body>
<header>@include('partials.nav')</header>
<main>@yield('content')</main>
</body>
</html>
@extends('layouts.app')
@section('title', 'قائمة الطلاب')
@section('content')
<h1>الطلاب</h1>
@foreach($students as $student)
<p>{{ $student->name }}</p>
@endforeach
@endsection
| التوجيه | الدور |
|---|---|
@extends('layouts.app') | يرث الصفحة من القالب الأب |
@section('content') ... @endsection | يحدد محتوى قسم معيّن |
@yield('content') | في الأب: مكان إدراج محتوى القسم |
{{ $variable }} يعرض قيمة مُهربة (آمنة من XSS). {!! $html !!} يعرض HTML خام — استخدمه بحذر.
CSRF (Cross-Site Request Forgery) هجوم يجعل المتصفح يرسل طلباً نيابة عن مستخدم مسجّل دون علمه. Laravel يولّد رمزاً سرياً لكل جلسة ويتحقق منه في طلبات POST/PUT/DELETE.
في أي نموذج يرسل بيانات:
<form method="POST" action="{{ route('students.store') }}">
@csrf
<input type="text" name="name" required>
<button type="submit">حفظ</button>
</form>
بدون @csrf Laravel يرفض الطلب برسالة 419 Page Expired. هذا سلوك مقصود للحماية.
Laravel UI حزمة تضيف تسجيل دخول، تسجيل حساب، استعادة كلمة المرور، وواجهات Bootstrap/Vue (حسب الإعداد). مفيدة لتوفير وقت في مشاريع التعلم والمشاريع الصغيرة.
composer require laravel/ui
php artisan ui bootstrap --auth
npm install && npm run dev
php artisan migrate
بعدها تحصل على مسارات مثل /login و /register وملفات Blade جاهزة يمكن تخصيصها.
لا تُخزَّن كلمات المرور كنص صريح أبداً. Laravel يستخدم Hash::make() أو bcrypt() لتوليد تجزئة (hash) أحادية الاتجاه.
use Illuminate\Support\Facades\Hash;
// عند التسجيل
$user->password = Hash::make($request->password);
// عند تسجيل الدخول
if (Hash::check($request->password, $user->password)) {
// كلمة المرور صحيحة
}
في Model المستخدم يمكن إضافة 'password' => 'hashed' في $casts (Laravel 10+) لتشفير تلقائي عند الحفظ.