التعامل مع قاعدة البيانات بسهولة Models و Eloquent
بعد أن تعلمنا في الدرس الثامن كيفية إنشاء قاعدة البيانات والجداول باستخدام Migrations، أصبح لدينا الآن مكان لتخزين بيانات التطبيق.
لكن هناك سؤال مهم:
- كيف نتعامل مع هذه البيانات من داخل Laravel؟
- كيف نضيف مقالًا جديدًا؟
- كيف نعرض المقالات الموجودة؟
- كيف نعدل مقالًا؟
- كيف نحذف سجلًا؟
- وهل يجب أن نكتب SQL يدويًا في كل مرة؟
الإجابة هي: Eloquent ORM.
يعتبر Eloquent من أهم الأجزاء في Laravel، لأنه يوفر طريقة بسيطة ومنظمة للتعامل مع قواعد البيانات من خلال Models بدلًا من كتابة استعلامات SQL بشكل مباشر في كل عملية.
في هذا الدرس سنتعرف على Models وEloquent، وسنتعلم إنشاء Model، وربطه بجدول قاعدة البيانات، وقراءة البيانات، وإضافة سجلات جديدة، وتعديلها وحذفها، بالإضافة إلى أهم طرق البحث والاستعلام، وشرح Mass Assignment وfillable، ثم سنبني مثالًا عمليًا كاملًا على نظام المقالات.
ما هو Eloquent ORM؟
Eloquent هو نظام ORM مدمج داخل Laravel.
ORM اختصار لـ:
Object-Relational Mapping
أي أنه يسمح لنا بالتعامل مع سجلات قاعدة البيانات باستخدام Objects وModels في PHP بدلًا من التعامل مع SQL في كل مرة.
في Laravel، يكون لكل جدول عادة Model يمثل هذا الجدول. ومن خلال هذا Model يمكننا استرجاع البيانات وإضافتها وتعديلها وحذفها.
بدل أن نكتب استعلام SQL مثل:
SELECT * FROM articles;
يمكننا باستخدام Eloquent كتابة:
Article::all();
وبدل:
SELECT * FROM articles WHERE id = 1;
يمكننا كتابة:
Article::find(1);
الفكرة ليست فقط تقليل عدد الأسطر، وإنما جعل كود التطبيق أكثر وضوحًا وتنظيمًا.
ما هو Model؟
الـ Model هو Class في Laravel يمثل نوعًا معينًا من البيانات.
مثلًا لدينا جدول:
articles
يمكن أن يكون لدينا Model اسمه:
Article
لدينا:
Database Table
↓
articles
↑
|
Article
Model
ومن خلال Article يمكننا التعامل مع بيانات جدول articles.
كذلك:
users
يمثله عادة:
User
وجدول:
categories
يمثله:
Category
وهكذا.
توجد Models التي ينشئها Laravel عادة داخل:
app/Models
وتقوم بتمديد Illuminate\Database\Eloquent\Model.
إنشاء أول Model
لنفترض أننا نريد إنشاء Model للمقالات.
يمكننا استخدام:
php artisan make:model Article
بعد تنفيذ الأمر سيظهر ملف:
app/Models/Article.php
وقد يكون محتواه الأساسي مشابهًا:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
//
}
لاحظ أن الـ Model يرث من:
Model
من Laravel.
وهذا هو الذي يمنحه قدرات Eloquent.
إنشاء Model مع Migration
إذا كنت تريد إنشاء Model وMigration في نفس الوقت، يمكنك استخدام:
php artisan make:model Article --migration
أو الاختصار:
php artisan make:model Article -m
وهذا سينشئ:
app/Models/Article.php
بالإضافة إلى Migration داخل:
database/migrations
Laravel يوفر أيضًا خيارات أخرى لإنشاء Factory وSeeder وController وForm Requests مع Model واحد.
مثلًا:
php artisan make:model Article -mfsc
يمكن أن ينشئ Model وMigration وFactory وSeeder وController.
وهذا مفيد عندما تبدأ مشروعًا جديدًا وتعرف أنك ستحتاج إلى هذه الملفات.
كيف يعرف Eloquent اسم الجدول؟
هنا تظهر واحدة من أهم قواعد Laravel.
إذا كان لدينا Model اسمه:
Article
فإن Eloquent يتوقع افتراضيًا أن يكون اسم الجدول:
articles
أي اسم Model بصيغة الجمع وsnake_case.
مثال:
User ↓ users Article ↓ articles Category ↓ categories BlogPost ↓ blog_posts
هذه الاتفاقيات تجعل Laravel قادرًا على معرفة اسم الجدول دون الحاجة إلى كتابته داخل كل Model.
تحديد اسم الجدول يدويًا
أحيانًا يكون اسم الجدول مختلفًا عن Convention.
في Laravel 13 يمكن تحديد اسم الجدول باستخدام Table Attribute:
use Illuminate\Database\Eloquent\Attributes\Table;
use Illuminate\Database\Eloquent\Model;
#[Table('my_articles')]
class Article extends Model
{
//
}
وبذلك سيستخدم Model جدول:
my_articles
بدل:
articles
في المشاريع التي تتبع Convention الخاصة بـ Laravel، غالبًا لن تحتاج إلى ذلك.
Primary Key
يفترض Eloquent افتراضيًا أن المفتاح الأساسي للجدول يسمى:
id
مثل:
articles id title content
إذا كان الجدول يستخدم اسمًا مختلفًا للمفتاح الأساسي، يمكن تخصيص ذلك في Model باستخدام إعدادات الجدول المناسبة.
لكن في بداية تعلم Laravel، يفضل الالتزام بالـ Convention:
id
لأن ذلك يجعل التعامل مع Eloquent أسهل.
Laravel يدعم أيضًا مفاتيح UUID وULID عند الحاجة، لكن هذه المواضيع يمكن تأجيلها إلى مرحلة متقدمة.
Timestamps في Eloquent
إذا كان جدولك يحتوي على:
created_at updated_at
فإن Eloquent يتعامل معهما تلقائيًا عند إنشاء وتعديل Model.
ولهذا السبب كنا نستخدم في Migration:
$table->timestamps();
فعندما تقوم بإنشاء سجل:
$article->save();
يمكن لـ Eloquent تحديث:
created_at updated_at
تلقائيًا.
وهذا أحد الأسباب التي تجعل timestamps() شائعًا جدًا في جداول Laravel.
قراءة البيانات باستخدام Eloquent
بعد إنشاء:
Article
يمكننا البدء في قراءة البيانات.
أبسط طريقة هي:
$articles = Article::all();
هذا يعيد جميع المقالات الموجودة في جدول:
articles
ثم يمكننا المرور عليها:
foreach ($articles as $article) {
echo $article->title;
}
الدالة all() تعيد Collection من نماذج Eloquent، وليست مجرد Array عادية.
ما هي Collection؟
عندما تنفذ:
Article::all();
ستحصل على:
Illuminate\Database\Eloquent\Collection
وهي مجموعة من Models.
مثلًا:
$articles = Article::all();
foreach ($articles as $article) {
echo $article->title;
}
يمكن التعامل معها باستخدام العديد من أدوات Collections الموجودة في Laravel.
وهذا يجعل التعامل مع مجموعة البيانات مريحًا جدًا.
البحث عن سجل باستخدام ID
إذا كنت تعرف ID المقال، يمكنك استخدام:
$article = Article::find(1);
هذا يبحث عن المقال الذي يحمل:
id = 1
إذا كان موجودًا، تحصل على Model.
وإذا لم يكن موجودًا، ستكون النتيجة:
null
مثلًا:
$article = Article::find(1);
if ($article) {
echo $article->title;
}
findOrFail() Laravel
أحيانًا لا نريد الحصول على null إذا لم يوجد السجل.
بل نريد أن يتعامل Laravel مع الحالة كـ 404.
هنا يمكننا استخدام:
$article = Article::findOrFail(1);
إذا كان المقال موجودًا، نحصل عليه.
أما إذا لم يكن موجودًا، فإن Laravel يرمي ModelNotFoundException، ويمكن أن ينتج عن ذلك استجابة HTTP من نوع 404 عندما لا يتم التقاط الاستثناء.
وهذا مفيد جدًا في Controllers.
مثلًا:
public function show($id)
{
$article = Article::findOrFail($id);
return view('articles.show', compact('article'));
}
بدل كتابة:
if (!$article) {
abort(404);
}
يمكننا الاعتماد على:
findOrFail()
first() Laravel
إذا أردنا الحصول على أول سجل يطابق شرطًا:
$article = Article::where('is_published', true)
->first();
أو يمكن استخدام:
$article = Article::first();
للحصول على أول Model.
Laravel يوفر أيضًا:
firstWhere()
مثل:
$article = Article::firstWhere('is_published', true);
وهذه الطرق مخصصة عندما نريد Model واحدًا بدل Collection كاملة.
استخدام where()
من أهم أدوات Eloquent:
where()
مثلًا:
$articles = Article::where('is_published', true)->get();
هذا يعني:
أحضر المقالات التي يكون فيها
is_publishedيساويtrue.
مثال آخر:
$articles = Article::where('title', 'Laravel')->get();
ويمكن استخدام أكثر من شرط:
$articles = Article::where('is_published', true)
->where('category_id', 2)
->get();
وهذا يجعل الاستعلامات سهلة القراءة.
where مع المقارنة
يمكنك تحديد نوع المقارنة:
$articles = Article::where('id', '>', 10)->get();
أو:
$articles = Article::where('views', '>=', 100)->get();
أو:
$articles = Article::where('status', '!=', 'draft')->get();
الصيغة العامة:
where(
'column',
'operator',
'value'
)
orderBy()
يمكن ترتيب النتائج.
مثلًا:
$articles = Article::orderBy('created_at', 'desc')->get();
يعني:
أحضر المقالات مرتبة من الأحدث إلى الأقدم.
ويمكن استخدام:
orderBy('title', 'asc')
للترتيب الأبجدي التصاعدي.
latest()
Laravel يوفر طريقة سهلة:
$articles = Article::latest()->get();
وهي مناسبة جدًا عندما تريد الحصول على السجلات الأحدث أولًا.
مثلًا في صفحة المقالات:
$articles = Article::latest()->get();
ثم ترسلها إلى View:
return view('articles.index', compact('articles'));
limit()
إذا كنت تريد عددًا محددًا من النتائج:
$articles = Article::latest()
->limit(10)
->get();
هذا مفيد عندما تريد عرض آخر 10 مقالات مثلًا.
count()
يمكنك معرفة عدد السجلات:
$count = Article::count();
أو:
$count = Article::where('is_published', true)->count();
وهذا مفيد في الإحصائيات ولوحات التحكم.
إنشاء سجل جديد باستخدام save()
يمكن إنشاء Article جديد بهذه الطريقة:
$article = new Article; $article->title = 'تعلم Laravel'; $article->slug = 'learn-laravel'; $article->content = 'محتوى المقال'; $article->save();
عند استدعاء:
save()
سيقوم Eloquent بحفظ السجل في قاعدة البيانات، وتتم إدارة created_at وupdated_at تلقائيًا إذا كانت timestamps مفعلة.
إنشاء سجل باستخدام create()
هناك طريقة مختصرة:
$article = Article::create([
'title' => 'تعلم Laravel',
'slug' => 'learn-laravel',
'content' => 'محتوى المقال',
]);
لكن هناك نقطة أمنية مهمة جدًا.
عند استخدام:
create()
يجب تحديد الحقول التي يسمح Laravel بتعبئتها باستخدام Mass Assignment protection. في Laravel 13 يمكن استخدام Fillable Attribute لتحديد الحقول المسموح بها.
Mass Assignment
لنفترض أن لدينا:
Article::create($request->all());
هذه الطريقة قد تكون خطيرة إذا كانت جميع حقول Request تمر مباشرة إلى Model.
لماذا؟
لأن المستخدم قد يرسل حقلًا لم تكن تقصده.
مثلًا إذا كان لدينا:
is_admin
وأنت لا تريد للمستخدم التحكم فيه، فقد تصبح هناك مشكلة أمنية إذا سمحت بتمرير البيانات بلا تقييد.
ولهذا يوفر Laravel حماية Mass Assignment.
استخدام Fillable في Laravel 13
في Laravel 13 يمكن تعريف الحقول القابلة للتعبئة باستخدام:
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Model;
#[Fillable([
'title',
'slug',
'content',
])]
class Article extends Model
{
//
}
الآن يمكن استخدام:
Article::create([
'title' => 'تعلم Laravel',
'slug' => 'learn-laravel',
'content' => 'محتوى المقال',
]);
بينما الحقول التي لم نسمح بها لن تكون ضمن Mass Assignment.
لماذا Mass Assignment مهمة؟
تخيل أن جدول المستخدمين يحتوي:
name email password is_admin
وأنت كتبت:
User::create($request->all());
قد يحاول شخص إرسال:
is_admin = true
إذا لم تكن قد ضبطت الحماية بشكل صحيح.
لذلك من المهم أن تحدد بوضوح ما الذي يسمح للتطبيق بتعبئته.
تحديث Model
لنفرض أننا حصلنا على المقال:
$article = Article::find(1);
يمكننا تعديل عنوانه:
$article->title = 'Laravel للمبتدئين';
ثم:
$article->save();
وبذلك يتم تحديث السجل في قاعدة البيانات.
استخدام update()
يمكن أيضًا استخدام:
$article->update([
'title' => 'Laravel للمبتدئين',
]);
لكن عند استخدام update() بهذه الطريقة يجب الانتباه أيضًا إلى Mass Assignment إذا كنت تستخدم مصفوفة attributes على Model.
updateOrCreate()
هناك حالات تريد فيها:
إذا وجد السجل، قم بتحديثه، وإذا لم يوجد، أنشئه.
هنا يمكن استخدام:
Article::updateOrCreate(
[
'slug' => 'learn-laravel',
],
[
'title' => 'تعلم Laravel',
'content' => 'محتوى المقال',
]
);
إذا وجد Laravel سجلًا مطابقًا للـ slug، سيقوم بتحديثه.
أما إذا لم يجده، فسيقوم بإنشاء سجل جديد.
Laravel يوفر updateOrCreate() لهذا النوع من العمليات، ويقوم بحفظ النتيجة مباشرة.
firstOrCreate()
طريقة أخرى مفيدة:
Article::firstOrCreate([
'slug' => 'learn-laravel',
]);
إذا وجد السجل، يعيده.
وإذا لم يجده، ينشئ سجلًا جديدًا.
يمكن أيضًا تمرير بيانات إضافية عند الإنشاء:
Article::firstOrCreate(
[
'slug' => 'learn-laravel',
],
[
'title' => 'تعلم Laravel',
'content' => 'محتوى المقال',
]
);
Laravel يفرق بين firstOrCreate() وfirstOrNew()؛ فـ firstOrCreate() يحفظ السجل الجديد مباشرة، بينما firstOrNew() يعيد Model جديدًا دون حفظه حتى تستدعي save().
حذف سجل
لحذف مقال:
$article = Article::find(1); $article->delete();
أو يمكنك حذف سجل مباشرة بواسطة ID:
Article::destroy(1);
ويمكن أيضًا:
Article::destroy([1, 2, 3]);
لحذف عدة سجلات.
الحذف باستخدام Query
يمكن حذف مجموعة من السجلات:
Article::where('is_published', false)->delete();
لكن يجب الانتباه إلى أن عمليات الحذف الجماعي بهذه الطريقة لا تقوم بتحميل كل Model بشكل منفصل، وبالتالي لا يتم إطلاق أحداث Model لكل سجل كما يحدث عند حذف Models فردية.
Soft Deletes
في بعض التطبيقات لا نريد حذف البيانات فعليًا.
مثلًا إذا قام مدير الموقع بحذف مقال، قد نريد الاحتفاظ به في قاعدة البيانات حتى يمكن استعادته لاحقًا.
هنا يمكن استخدام:
Soft Deletes
بدل حذف السجل فعليًا، يتم تسجيل وقت الحذف في:
deleted_at
ولتمكين ذلك نستخدم:
use Illuminate\Database\Eloquent\SoftDeletes;
class Article extends Model
{
use SoftDeletes;
}
ويجب أيضًا أن يحتوي الجدول على:
$table->softDeletes();
عند استخدام Soft Deletes، يتم استبعاد السجلات المحذوفة مؤقتًا من الاستعلامات العادية، بينما تبقى البيانات في قاعدة البيانات.
مثال عملي كامل على Article Model
لننشئ Model لمقالات موقعنا.
يمكن أن يكون:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Model;
#[Fillable([
'title',
'slug',
'excerpt',
'content',
'is_published',
])]
class Article extends Model
{
//
}
لدينا الآن Model يمثل:
articles
ويسمح بالتعبئة الجماعية للحقول:
title slug excerpt content is_published
استخدام Model داخل Controller
لنفرض أن لدينا:
ArticleController
ونريد عرض جميع المقالات.
يمكننا كتابة:
use App\Models\Article;
public function index()
{
$articles = Article::latest()->get();
return view('articles.index', compact('articles'));
}
هنا حدثت عدة خطوات:
Controller ↓ Article Model ↓ Database ↓ articles ↓ Collection ↓ Blade View
عرض المقالات داخل Blade
في:
resources/views/articles/index.blade.php
يمكننا كتابة:
<h1>المقالات</h1>
@foreach ($articles as $article)
<article>
<h2>{{ $article->title }}</h2>
<p>
{{ $article->excerpt }}
</p>
<a href="{{ route('articles.show', $article) }}">
اقرأ المقال
</a>
</article>
@endforeach
لاحظ كيف أصبح لدينا الآن تدفق كامل:
Route ↓ Controller ↓ Model ↓ Database ↓ Controller ↓ View
وهذا هو الاستخدام الحقيقي لـ Laravel.
استقبال البيانات من Form وحفظها
في الدرس السابع تعلمنا Validation.
يمكن الآن دمج Validation مع Eloquent.
مثلًا:
public function store(Request $request)
{
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
Article::create($validated);
return redirect()
->route('articles.index')
->with('success', 'تم إنشاء المقال بنجاح.');
}
هنا لدينا:
Form ↓ Request ↓ Validation ↓ validated() ↓ Article::create() ↓ Database
وهذه واحدة من أهم التدفقات التي ستستخدمها باستمرار في Laravel.
لماذا نستخدم validated()؟
بدل:
Article::create($request->all());
نستخدم:
$validated = $request->validate([
'title' => ['required', 'string'],
'content' => ['required', 'string'],
]);
Article::create($validated);
والسبب أن البيانات التي تمر إلى Model هي البيانات التي اجتازت Validation فقط.
وهذا يجعل الكود أكثر وضوحًا وأمانًا.
التعامل مع Query Builder داخل Eloquent
Eloquent لا يمنعك من استخدام طرق الاستعلام المختلفة.
مثلًا:
$articles = Article::where('is_published', true)
->orderBy('created_at', 'desc')
->limit(10)
->get();
يمكنك بناء الاستعلام خطوة بخطوة.
فكرة Eloquent الأساسية أن Model يعمل أيضًا كواجهة Query Builder، ولذلك يمكنك إضافة شروط وترتيب وحدود ثم استخدام get() للحصول على النتائج.
الفرق بين get() وfirst()
من الأخطاء الشائعة الخلط بين:
get()
و:
first()
get()
تعيد مجموعة من النتائج:
$articles = Article::where('is_published', true)->get();
النتيجة:
Collection
first()
تعيد Model واحدًا:
$article = Article::where('slug', $slug)->first();
النتيجة:
Article Model
أو:
null
إذا لم يوجد شيء.
الفرق بين find() وwhere()
يمكن استخدام:
Article::find(5);
عندما تعرف الـ Primary Key.
أما:
Article::where('slug', 'learn-laravel')->first();
فهي مناسبة عندما تريد البحث باستخدام عمود آخر.
بشكل مبسط:
find() ↓ Primary Key where() ↓ أي شرط مناسب
التعامل مع البيانات الكبيرة
إذا كان جدولك يحتوي على آلاف أو عشرات الآلاف من السجلات، لا يكون من المناسب دائمًا تحميلها كلها باستخدام:
Article::all();
دفعة واحدة.
يمكن استخدام:
Article::chunk(200, function ($articles) {
foreach ($articles as $article) {
// معالجة المقال
}
});
يقوم chunk() بمعالجة البيانات على دفعات، مما يقلل استهلاك الذاكرة عند التعامل مع أعداد كبيرة من السجلات.
وهذا موضوع مهم عندما تبدأ ببناء تطبيقات تحتوي على بيانات كبيرة.
CRUD كامل للمقالات
أصبح بإمكاننا الآن تصور CRUD كامل.
CRUD تعني:
Create Read Update Delete
أي:
إنشاء قراءة تعديل حذف
Create
Article::create([
'title' => 'Laravel',
'slug' => 'laravel',
'content' => 'تعلم Laravel',
]);
Read
$articles = Article::all();
Update
$article = Article::findOrFail(1);
$article->update([
'title' => 'Laravel للمبتدئين',
]);
Delete
$article = Article::findOrFail(1); $article->delete();
بهذه العمليات الأربع يمكنك بناء الأساس لمعظم أنظمة إدارة البيانات.
مثال على دورة CRUD داخل Laravel
لنفترض أن المستخدم يريد إضافة مقال.
يحدث الآتي:
المستخدم ↓ Form ↓ POST /articles ↓ Route ↓ ArticleController@store ↓ Validation ↓ Article Model ↓ Database ↓ Redirect
وعندما يريد عرض المقال:
GET /articles/1 ↓ Route ↓ Controller ↓ Article::findOrFail(1) ↓ View ↓ HTML
وعندما يريد تعديله:
Form ↓ PUT /articles/1 ↓ Controller ↓ Validation ↓ Article ↓ update() ↓ Database
وعندما يريد حذفه:
DELETE /articles/1 ↓ Controller ↓ Article ↓ delete() ↓ Database
وهنا تبدأ الصورة الكبيرة لـ Laravel في الظهور.
أخطاء شائعة عند استخدام Eloquent
1 - نسيان إنشاء Migration
وجود:
Article.php
لا يعني أن جدول:
articles
موجود.
يجب أن تكون قد أنشأت Migration وشغلت:
php artisan migrate
2 - اسم الجدول لا يتوافق مع Model
إذا كان لديك:
Article
يتوقع Eloquent:
articles
إذا كان جدولك باسم مختلف، يجب تعريفه بشكل صريح.
3 - استخدام create() بدون Fillable
إذا كتبت:
Article::create($data);
يجب ضبط Mass Assignment protection باستخدام Fillable أو الآلية المناسبة في Model. Laravel يحمي Models افتراضيًا من Mass Assignment غير المسموح به.
4 - استخدام all() مع جدول ضخم
لا تستخدم:
Article::all();
بشكل عشوائي على جداول ضخمة إذا كنت لا تحتاج كل السجلات.
يمكن استخدام:
paginate() chunk() lazy() cursor()
بحسب السيناريو.
5 - عدم استخدام findOrFail() عند الحاجة إلى 404
إذا كان الهدف صفحة تفاصيل مقال، يمكن أن يكون:
Article::findOrFail($id);
أفضل من:
Article::find($id);
إذا كان عدم وجود المقال يجب أن يؤدي إلى 404.
أفضل ممارسات استخدام Eloquent
استخدم Models بدل وضع SQL في كل مكان
اجعل التعامل مع البيانات منظمًا داخل Models وطبقات التطبيق المناسبة.
1 - استخدم أسماء واضحة
مثل:
Article Category Comment User
بدل أسماء غامضة.
2 -استخدم Validation قبل الحفظ
لا تحفظ بيانات Form مباشرة قبل التحقق منها.
3 - لا تمرر Request بالكامل إلى create()
بدل:
>Article::create($request->all());
استخدم البيانات التي تم التحقق منها:
Article::create($validated);
4 - استخدم Mass Assignment protection
حدد الحقول التي يسمح للتطبيق بتعبئتها.
5 - لا تحمل بيانات أكثر مما تحتاج
إذا كان هدفك التعامل مع عدد محدود من السجلات، استخدم شروطًا وحدودًا مناسبة.
تمرين عملي
الآن جاء دورك.
أنشئ Model باسم:
php artisan make:model Article -m
ثم تأكد من وجود Migration لجدول:
articles
واجعله يحتوي على:
id title slug excerpt content is_published created_at updated_at
ثم شغّل:
php artisan migrate
بعد ذلك قم بإعداد Model للسماح بالحقول المناسبة لـ Mass Assignment.
ثم جرّب في Controller:
Article::create([
'title' => 'أول مقال في Laravel',
'slug' => 'first-laravel-article',
'excerpt' => 'مقال تجريبي',
'content' => 'هذا محتوى المقال.',
'is_published' => true,
]);
بعد ذلك جرّب:
$articles = Article::latest()->get();
ثم:
$article = Article::find(1);
ثم:
$article = Article::findOrFail(1);
ثم عدّل المقال:
$article->update([
'title' => 'عنوان جديد للمقال',
]);
وأخيرًا احذفه:
$article->delete();
إذا استطعت تنفيذ هذه العمليات، فقد تعلمت الأساس الحقيقي لـ Eloquent وCRUD.
في هذا الدرس تعرفنا على Models وEloquent ORM، وهما من أهم أجزاء Laravel في التعامل مع قاعدة البيانات.
تعلمنا أن Model يمثل جدولًا في قاعدة البيانات، وأن Model مثل:
Article
يرتبط افتراضيًا بجدول:
articles
وتعلمنا إنشاء Model باستخدام:
php artisan make:model Article
وإنشاء Model مع Migration باستخدام:
php artisan make:model Article -m
ثم تعلمنا قراءة البيانات باستخدام:
Article::all(); Article::find(1); Article::findOrFail(1); Article::first(); Article::where(...)->get();
وتعلمنا ترتيب النتائج باستخدام:
latest() orderBy()
والحصول على عدد النتائج باستخدام:
count()
ثم تعلمنا إنشاء البيانات باستخدام:
save() create()
وتحديثها باستخدام:
save() update() updateOrCreate()
وحذفها باستخدام:
delete() destroy()
وتعرفنا على:
Mass Assignment Fillable Soft Deletes Collections Chunking
كما رأينا كيف يمكن دمج:
Requests Validation Controllers Models Database Views
في دورة واحدة متكاملة.
العلاقة بين الدروس السابقة وهذا الدرس
حتى الآن أصبح لدينا المسار التالي:
Routing ↓ Controller ↓ Request ↓ Validation ↓ Model ↓ Eloquent ↓ Database ↓ View
وهذا يعني أن البيانات التي يدخلها المستخدم يمكن أن تمر عبر مراحل واضحة ومنظمة قبل أن تصل إلى قاعدة البيانات.
مثلًا عند إنشاء مقال:
Blade Form ↓ POST Request ↓ Controller ↓ Validation ↓ Article Model ↓ Eloquent ↓ articles Table
وهذه هي الطريقة التي يبدأ بها تطبيق Laravel الحقيقي في أخذ شكل واضح ومنظم.
الآن أصبح لدينا:
- Database
- Migrations
- Models
- Eloquent
- CRUD
لكن هناك سؤال مهم:
ماذا لو كان لدينا أكثر من جدول؟
مثلًا:
users articles comments categories
- وكيف نربط المقال بالمستخدم؟
- وكيف نعرف أن المستخدم لديه عدة مقالات؟
- وكيف نربط المقالات بالتصنيفات؟
- وكيف نتعامل مع العلاقات بين الجداول؟
هنا يأتي الدرس القادم.
في الدرس العاشر سنتعلم:
Eloquent Relationships
وسنشرح بالتفصيل:
hasOne hasMany belongsTo belongsToMany
وسنتعلم أيضًا:
Foreign Keys Pivot Tables Eager Loading with() load()
وسنطبق ذلك على مثال حقيقي يربط:
User ↓ Articles ↓ Comments
وبذلك سننتقل من مجرد التعامل مع جدول واحد إلى بناء نظام بيانات مترابط باستخدام Eloquent.
