العمل مع نماذج Laravel: عمليات CRUD

Amine
30/08/2024

المقدمة

تُعد نماذج Eloquent في Laravel من أقوى الأدوات التي تسهل التفاعل مع قواعد البيانات بطريقة فعّالة وسلسة. يوفر Eloquent ORM (Object-Relational Mapping) واجهة برمجية تُمكِّن المطورين من إجراء عمليات CRUD (إنشاء، قراءة، تحديث، حذف) على البيانات دون الحاجة إلى كتابة استعلامات SQL معقدة. بالإضافة إلى ذلك، يدعم Eloquent العديد من الميزات المتقدمة مثل إدارة العلاقات بين الجداول، والتحقق من صحة البيانات، والمعاملات، وغيرها الكثير. في هذا الدليل الشامل، سنستعرض كيفية إنشاء واستخدام نماذج Eloquent في Laravel بطرق موسعة ومتقدمة.

الخطوة 1: إنشاء نموذج Eloquent جديد

لإنشاء نموذج Eloquent جديد، نستخدم أداة سطر الأوامر Artisan التي توفرها Laravel. افتح سطر الأوامر في مجلد مشروع Laravel الخاص بك واستخدم الأمر التالي:

php artisan make:model Post -m

يُنشئ هذا الأمر نموذجًا جديدًا يُسمى Post.php في مجلد app/Models، بالإضافة إلى ملف هجرة (Migration) لإنشاء جدول posts في قاعدة البيانات.

الخطوة 2: إعداد قاعدة البيانات والهجرات

قبل البدء في استخدام النموذج، نحتاج إلى إعداد قاعدة البيانات وتشغيل الهجرات لإنشاء الجداول اللازمة. تأكد من إعداد اتصال قاعدة البيانات في ملف .env الخاص بمشروعك:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

بعد إعداد الاتصال، يمكنك تحرير ملف الهجرة create_posts_table.php في مجلد database/migrations لتعريف هيكل جدول posts:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('posts');
    }
};

بعد تعريف الهجرة، نفّذها باستخدام الأمر:

php artisan migrate

سيقوم هذا الأمر بإنشاء جدول posts في قاعدة البيانات وفقًا للتعريف المحدد.

الخطوة 3: إعداد النموذج

يمكنك تخصيص النموذج بتحديد الحقول القابلة للتعبئة (fillable) والحقول المخفية (hidden) وغيرها من الخصائص. افتح ملف Post.php وأضف الإعدادات التالية:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content'];

    // لإخفاء الحقول من الواجهة الأمامية
    // protected $hidden = ['created_at', 'updated_at'];
}

يحدد هذا الإعداد الحقول التي يمكن تعبئتها بشكل جماعي لتجنب هجمات التخصيص الجماعي.

الخطوة 4: إدارة العلاقات بين النماذج

يدعم Eloquent إدارة العلاقات بين الجداول بسهولة. لنفترض أن كل مقال (Post) يمكن أن يحتوي على تعليقات (Comments). سنقوم بإنشاء نموذج Comment وتحديد العلاقة بينهما.

php artisan make:model Comment -m

قم بتعريف هيكل جدول comments في ملف الهجرة:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('post_id');
            $table->text('content');
            $table->timestamps();

            $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
        });
    }

    public function down()
    {
        Schema::dropIfExists('comments');
    }
};

بعد تشغيل الهجرات باستخدام php artisan migrate، قم بتعريف العلاقة في نموذج Post ونموذج Comment:


// في Post.php
public function comments()
{
    return $this->hasMany(Comment::class);
}

// في Comment.php
public function post()
{
    return $this->belongsTo(Post::class);
}

تُمكِّنك هذه العلاقات من جلب البيانات المرتبطة بسهولة باستخدام Eloquent.

الخطوة 5: إجراء عمليات CRUD باستخدام النموذج

باستخدام Eloquent، يمكنك إجراء عمليات CRUD بسهولة على البيانات في قاعدة البيانات. لنقم بمراجعة كيفية تنفيذ كل عملية بشكل موسع:

1. إنشاء سجل جديد (Create)

لإضافة سجل جديد إلى قاعدة البيانات، يمكنك استخدام طريقة create أو طريقة save:

// باستخدام طريقة create
$post = Post::create([
    'title' => 'عنوان المقال',
    'content' => 'محتوى المقال'
]);

// أو باستخدام طريقة save
$post = new Post();
$post->title = 'عنوان المقال';
$post->content = 'محتوى المقال';
$post->save();

يمكنك أيضًا إنشاء سجلات مرتبطة، مثل إنشاء تعليق مرتبط بمقال:

$comment = new Comment([
    'content' => 'هذا تعليق رائع!'
]);
$post->comments()->save($comment);

2. قراءة البيانات (Read)

لجلب البيانات من قاعدة البيانات، يمكنك استخدام عدة طرق من Eloquent مثل all، find، أو where:

// جلب جميع المقالات
$posts = Post::all();

// جلب مقال بالمعرف 1
$post = Post::find(1);

// جلب المقال الأول الذي يحمل عنوان معين
$post = Post::where('title', 'عنوان المقال')->first();

// استخدام التحميل المسبق للعلاقات
$posts = Post::with('comments')->get();

يمكنك أيضًا استخدام الاستعلامات المتقدمة:

// جلب المقالات التي تحتوي على عنوان معين وترتيبها حسب تاريخ الإنشاء
$posts = Post::where('title', 'like', '%مقال%')
    ->orderBy('created_at', 'desc')
    ->get();

3. تحديث سجل موجود (Update)

لتحديث سجل موجود، يمكنك جلب السجل أولاً ثم استخدام طريقة update أو تعيين الخصائص يدويًا وحفظ التغييرات:

// استخدام طريقة update
$post = Post::find(1);
$post->update([
    'title' => 'عنوان جديد للمقال'
]);

// أو تعيين الخصائص يدويًا
$post->title = 'عنوان جديد للمقال';
$post->save();

يمكنك أيضًا تحديث السجلات المرتبطة:

$comment = Comment::find(1);
$comment->update([
    'content' => 'تم تحديث محتوى التعليق'
]);

4. حذف سجل (Delete)

لحذف سجل من قاعدة البيانات، استخدم طريقة delete:

// حذف سجل معين
$post = Post::find(1);
$post->delete();

// أو استخدام طريقة destroy لحذف سجل معين بالمعرف مباشرة
Post::destroy(1);

// حذف سجل مع تعليقاته باستخدام العلاقات
$post->comments()->delete();

يمكنك أيضًا استخدام الحذف الناعم (Soft Deletes) لحذف السجلات بطريقة تسمح باستعادتها لاحقًا.

5. الحذف الناعم (Soft Deletes)

يُمكِّنك الحذف الناعم من حذف السجلات دون إزالتها فعليًا من قاعدة البيانات. لتنفيذ الحذف الناعم، اتبع الخطوات التالية:

// في نموذج Post.php
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = ['title', 'content'];

    // ...
}

ثم أضف عمود deleted_at إلى جدول posts عبر الهجرة:

// في ملف الهجرة create_posts_table.php
$table->softDeletes();

بعد ذلك، يمكنك استخدام طرق الحذف الناعم:

// حذف السجل بشكل ناعم
$post = Post::find(1);
$post->delete();

// استرجاع السجلات المحذوفة
$trashed = Post::onlyTrashed()->get();

// استعادة سجل محذوف
$post->restore();

الخطوة 6: التحقق من صحة البيانات (Validation)

من المهم التحقق من صحة البيانات قبل حفظها في قاعدة البيانات لضمان سلامة البيانات ومنع الأخطاء. يمكنك تنفيذ التحقق من الصحة في وحدات التحكم (Controllers) أو باستخدام قواعد التحقق المخصصة. إليك كيفية القيام بذلك في وحدة تحكم:

public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|max:255',
        'content' => 'required',
    ]);

    Post::create($validated);

    return redirect()->route('posts.index')
        ->with('success', 'تم إنشاء المقال بنجاح.');
}

الخطوة 7: الوصول إلى البيانات (Accessors & Mutators)

تسمح لك الـ Accessors و Mutators بتعديل قيم الخصائص عند الوصول إليها أو تعيينها. على سبيل المثال، يمكنك تحويل عنوان المقال إلى أحرف كبيرة تلقائيًا:

// في Post.php

// Mutator لتعيين العنوان بأحرف كبيرة
public function setTitleAttribute($value)
{
    $this->attributes['title'] = ucfirst($value);
}

// Accessor للحصول على العنوان بأحرف كبيرة
public function getTitleAttribute($value)
{
    return strtoupper($value);
}

الخطوة 8: النطاقات (Scopes)

تُستخدم النطاقات لتجميع استعلامات معينة يمكن إعادة استخدامها بسهولة. على سبيل المثال، لنقم بإنشاء نطاق لجلب المقالات التي تحتوي على كلمة معينة في العنوان:

// في Post.php

public function scopeTitleContains($query, $word)
{
    return $query->where('title', 'like', '%' . $word . '%');
}

يمكنك استخدام هذا النطاق في الاستعلامات كما يلي:

$posts = Post::titleContains('Laravel')->get();

الخطوة 9: المعاملات (Transactions)

تسمح المعاملات بتنفيذ مجموعة من العمليات ككتلة واحدة، مما يضمن أن جميع العمليات تتم بنجاح أو تُلغى في حالة حدوث خطأ. إليك كيفية استخدام المعاملات في Eloquent:

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    $post = Post::create([
        'title' => 'مقال جديد',
        'content' => 'محتوى المقال الجديد'
    ]);

    $post->comments()->create([
        'content' => 'تعليق أول'
    ]);
});

الخطوة 10: التحميل المسبق للعلاقات (Eager Loading)

يساعد التحميل المسبق في تحسين أداء الاستعلامات عن طريق جلب العلاقات المرتبطة مع السجلات الأساسية في استعلام واحد. على سبيل المثال، لجلب جميع المقالات مع تعليقاتها:

$posts = Post::with('comments')->get();

الخطوة 11: Factories & Seeders

تُستخدم Factories & Seeders لإنشاء بيانات تجريبية أو بيانات أولية في قاعدة البيانات. لإنشاء Factory لنموذج Post، استخدم الأمر التالي:

php artisan make:factory PostFactory --model=Post

ثم قم بتعريف الـ Factory في ملف PostFactory.php:

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    protected $model = Post::class;

    public function definition()
    {
        return [
            'title' => $this->faker->sentence,
            'content' => $this->faker->paragraph,
        ];
    }
}

يمكنك استخدام Factories في Seeders لإنشاء بيانات أولية:

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        \App\Models\Post::factory(10)->create();
    }
}

الخطوة 12: Events & Observers

تسمح Events & Observers بالاستجابة لأحداث معينة في دورة حياة النموذج، مثل الإنشاء، التحديث، والحذف. لإنشاء Observer لنموذج Post، استخدم الأمر:

php artisan make:observer PostObserver --model=Post

ثم قم بتعريف الـ Observer في ملف PostObserver.php:

namespace App\Observers;

use App\Models\Post;

class PostObserver
{
    public function created(Post $post)
    {
        // منطق عند إنشاء مقال جديد
    }

    public function updated(Post $post)
    {
        // منطق عند تحديث مقال
    }

    public function deleted(Post $post)
    {
        // منطق عند حذف مقال
    }

    // يمكنك تعريف المزيد من الأحداث حسب الحاجة
}

لا تنسَ تسجيل الـ Observer في خدمة AppServiceProvider:

use App\Models\Post;
use App\Observers\PostObserver;

public function boot()
{
    Post::observe(PostObserver::class);
}

الخطوة 13: اختبار النماذج (Testing Models)

يُعد اختبار النماذج جزءًا أساسيًا من تطوير التطبيقات لضمان عملها بشكل صحيح. يمكنك استخدام PHPUnit لاختبار وظائف النماذج. إليك مثالًا لاختبار إنشاء مقال:

use Tests\TestCase;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;

class PostTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function it_creates_a_post()
    {
        $post = Post::factory()->create([
            'title' => 'اختبار عنوان',
            'content' => 'اختبار محتوى'
        ]);

        $this->assertDatabaseHas('posts', [
            'title' => 'اختبار عنوان',
            'content' => 'اختبار محتوى'
        ]);
    }
}

الخاتمة

توفر نماذج Eloquent في Laravel واجهة برمجية قوية ومرنة لإدارة البيانات والتفاعل مع قواعد البيانات بكفاءة عالية. من خلال هذا الدليل، تعرفنا على كيفية إنشاء النماذج، إدارة العلاقات، إجراء عمليات CRUD، واستخدام الميزات المتقدمة مثل التحقق من صحة البيانات، النطاقات، والمعاملات. استكشاف المزيد من ميزات Eloquent سيساعدك في بناء تطبيقات أكثر قوة وقابلية للصيانة. استمر في التعلم والتطبيق لتحقيق أقصى استفادة من إمكانيات Laravel وEloquent في مشاريعك المستقبلية.

التعليقات

اترك تعليقاً