مقالات علاء عامر

نقدم مجموعة شاملة من مقالات التعليمية الهامة في تطوير الويب لتحويل أفكارك إلى واقع رقمي

Eloquent ORM في Laravel: إتقان العلاقات والاستعلامات

Laravel 2026-01-01 علاء عامر

Eloquent ORM في Laravel: إتقان العلاقات والاستعلامات

دليل تخصصي من علاء عامر – مطور ومصمم مواقع وتطبيقات محترف

Eloquent ORM هو قلب Laravel لإدارة قواعد البيانات. يوفر طريقة أنيقة وبديهية للتعامل مع البيانات والعلاقات المعقدة.

2️⃣ العلاقات المتقدمة والمعقدة

نموذج Post مع علاقات معقدة:

<?php
// app/Models/Post.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'title', 'slug', 'content', 'excerpt', 'featured_image',
        'status', 'user_id', 'category_id', 'published_at',
        'meta_title', 'meta_description', 'reading_time'
    ];

    protected $casts = [
        'published_at' => 'datetime',
        'meta_keywords' => 'array',
        'settings' => 'array',
        'is_featured' => 'boolean'
    ];

    // العلاقات الأساسية
    public function author()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function tags()
    {
        return $this->belongsToMany(Tag::class)->withTimestamps();
    }

    public function comments()
    {
        return $this->hasMany(Comment::class)->whereNull('parent_id');
    }

    public function allComments()
    {
        return $this->hasMany(Comment::class);
    }

    // علاقة polymorphic للصور
    public function images()
    {
        return $this->morphMany(Image::class, 'imageable');
    }

    // علاقة للمراجعات
    public function revisions()
    {
        return $this->hasMany(PostRevision::class)->latest();
    }

    // علاقة المشاهدات
    public function views()
    {
        return $this->morphMany(View::class, 'viewable');
    }

    // علاقة الإعجابات
    public function likes()
    {
        return $this->morphMany(Like::class, 'likeable');
    }

    // المستخدمون الذين أعجبهم المقال
    public function likedByUsers()
    {
        return $this->morphToMany(User::class, 'likeable', 'likes')
                    ->withTimestamps();
    }

    // Scopes متقدمة
    public function scopePublished($query)
    {
        return $query->where('status', 'published')
                    ->where('published_at', '<=', now());
    }

    public function scopeFeatured($query)
    {
        return $query->where('is_featured', true);
    }

    public function scopeInCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }

    public function scopeByAuthor($query, $authorId)
    {
        return $query->where('user_id', $authorId);
    }

    public function scopePopular($query, $days = 30)
    {
        return $query->withCount(['views' => function($q) use ($days) {
                        $q->where('created_at', '>=', now()->subDays($days));
                    }])
                    ->orderBy('views_count', 'desc');
    }

    public function scopeWithRelations($query)
    {
        return $query->with(['author', 'category', 'tags']);
    }

    public function scopeSearch($query, $term)
    {
        return $query->where(function($q) use ($term) {
            $q->where('title', 'LIKE', "%{$term}%")
              ->orWhere('content', 'LIKE', "%{$term}%")
              ->orWhere('excerpt', 'LIKE', "%{$term}%");
        });
    }

    // Query Scopes مع معاملات
    public function scopePublishedBetween($query, $start, $end)
    {
        return $query->published()
                    ->whereBetween('published_at', [$start, $end]);
    }

    public function scopeWithMinReadingTime($query, $minutes)
    {
        return $query->where('reading_time', '>=', $minutes);
    }

    // Local Scopes للفلترة المعقدة
    public function scopeAdvancedFilter($query, array $filters)
    {
        return $query->when($filters['category'] ?? null, function($q, $category) {
                return $q->inCategory($category);
            })
            ->when($filters['author'] ?? null, function($q, $author) {
                return $q->byAuthor($author);
            })
            ->when($filters['status'] ?? null, function($q, $status) {
                return $q->where('status', $status);
            })
            ->when($filters['date_from'] ?? null, function($q, $date) {
                return $q->where('published_at', '>=', $date);
            })
            ->when($filters['date_to'] ?? null, function($q, $date) {
                return $q->where('published_at', '<=', $date);
            })
            ->when($filters['search'] ?? null, function($q, $term) {
                return $q->search($term);
            });
    }

    // Accessors
    public function getRouteKeyName()
    {
        return 'slug';
    }

    public function getReadingTimeAttribute($value)
    {
        return $value ?: $this->calculateReadingTime();
    }

    public function getIsPublishedAttribute()
    {
        return $this->status === 'published' &&
               $this->published_at <= now();
    }

    public function getExcerptAttribute($value)
    {
        return $value ?: Str::limit(strip_tags($this->content), 160);
    }

    // Helper Methods
    public function calculateReadingTime()
    {
        $wordCount = str_word_count(strip_tags($this->content));
        return ceil($wordCount / 200); // 200 words per minute
    }

    public function incrementViews($user = null)
    {
        $this->views()->create([
            'user_id' => $user?->id,
            'ip_address' => request()->ip(),
            'user_agent' => request()->userAgent()
        ]);

        $this->increment('views_count');
    }

    public function like($user)
    {
        if (!$this->isLikedBy($user)) {
            return $this->likes()->create(['user_id' => $user->id]);
        }
    }

    public function unlike($user)
    {
        return $this->likes()->where('user_id', $user->id)->delete();
    }

    public function isLikedBy($user)
    {
        if (!$user) return false;

        return $this->likes()->where('user_id', $user->id)->exists();
    }
}

4️⃣ تحسين الأداء مع Eloquent

تجنب N+1 Problem:

<?php
// مشكلة N+1 - سيئة
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name; // استعلام إضافي لكل مقال
}

// الحل - Eager Loading
$posts = Post::with('author')->get();
foreach ($posts as $post) {
    echo $post->author->name; // استعلام واحد فقط
}

// Eager Loading المشروط
$posts = Post::with(['author' => function($query) {
    $query->where('status', 'active');
}])->get();

// تحميل العلاقات لاحقاً
$posts = Post::all();
$posts->load('author', 'category');

// تحميل العلاقات المتداخلة
$posts = Post::with([
    'comments.user',
    'category.parent',
    'tags' => function($query) {
        $query->where('is_active', true);
    }
])->get();

استخدام Chunk للبيانات الكبيرة:

<?php
// معالجة البيانات الكبيرة بكفاءة
Post::published()
    ->chunk(100, function($posts) {
        foreach ($posts as $post) {
            // معالجة كل مقال
            $post->calculateReadingTime();
            $post->save();
        }
    });

// Lazy Collection للذاكرة المحدودة
Post::published()->lazy()->each(function($post) {
    // معالجة مقال واحد في كل مرة
    $post->updateSeoScore();
});

// Cursor للبيانات الضخمة
foreach (Post::published()->cursor() as $post) {
    // معالجة فعالة للذاكرة
    ProcessPostJob::dispatch($post);
}

Query Optimization:

<?php
// استعلامات محسنة للأداء
class OptimizedQueries
{
    public function getPopularPostsOptimized()
    {
        return Post::select([
                'id', 'title', 'slug', 'excerpt',
                'featured_image', 'published_at', 'views_count'
            ])
            ->with([
                'author:id,name,avatar',
                'category:id,name,slug'
            ])
            ->published()
            ->orderBy('views_count', 'desc')
            ->limit(10)
            ->get();
    }

    public function getCategoryStatsOptimized()
    {
        return Category::withCount([
                'posts as total_posts',
                'posts as published_posts' => function($query) {
                    $query->published();
                }
            ])
            ->with(['posts' => function($query) {
                $query->published()
                      ->latest()
                      ->limit(5)
                      ->select('id', 'title', 'slug', 'category_id');
            }])
            ->get();
    }

    public function getUserActivityStats($userId)
    {
        return DB::table('users')
            ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
            ->leftJoin('comments', 'users.id', '=', 'comments.user_id')
            ->select([
                'users.id',
                'users.name',
                DB::raw('COUNT(DISTINCT posts.id) as posts_count'),
                DB::raw('COUNT(DISTINCT comments.id) as comments_count'),
                DB::raw('SUM(posts.views_count) as total_views')
            ])
            ->where('users.id', $userId)
            ->groupBy('users.id', 'users.name')
            ->first();
    }
}

💡 أفضل الممارسات مع Eloquent

  1. استخدم Eager Loading لتجنب مشكلة N+1
  2. حدد الحقول المطلوبة باستخدام select()
  3. استخدم Scopes لإعادة استخدام الاستعلامات
  4. فعّل Model Caching للبيانات الثابتة
  5. استخدم Database Indexes للحقول المستعلمة كثيراً
  6. اتبع naming conventions لـ Laravel
  7. استخدم Accessors/Mutators بحذر لتجنب بطء الأداء

الخطوة التالية

تعلم Authentication & Authorization في Laravel لحماية تطبيقك وإدارة المستخدمين.

📩 هل تحتاج مساعدة في تطوير Eloquent Models؟

Laravel Eloquent ORM Database Relationships Query Builder Performance Models
قسم المقالة
Laravel

Eloquent ORM في Laravel: إتقان العلاقات والاستعلامات

دليل شامل لـ Eloquent ORM في Laravel، تعلم كيفية بناء العلاقات المعقدة، الاستعلامات المتقدمة، وتحسين الأداء.

Eloquent ORM في Laravel: إتقان العلاقات والاستعلامات
01

التواصل والاستشارة

تواصل مباشر عبر الواتساب أو الهاتف لفهم احتياجات مشروعك بدقة.

02

التخطيط والجدولة

وضع خطة عمل واضحة مع جدول زمني محدد لكل مرحلة من المشروع.

03

البرمجة والتطوير

تطوير المشروع بأحدث التقنيات لضمان الأداء والأمان العاليين.

04

المراجعة والتسليم

ختبار شامل ومراجعة دقيقة قبل التسليم النهائي للمشروع.

علاء عامر
علاء عامر

مطور ويب محترف بخبرة تزيد عن 10 سنوات في بناء حلول رقمية مبتكرة.

هل تحتاج هذه الخدمة؟

تواصل معي الآن للحصول على استشارة مجانية وعرض سعر

تواصل عبر واتساب رضاكم هو هدفنا الأسمى

عروض إضافية

  • صيانة وتحديث المواقع

    نحافظ على موقعك آمنًا ومحدّثًا دائمًا

  • ربط الأنظمة وواجهات البرمجة

    نربط أنظمتك بواجهات برمجية قوية ومرنة

  • تصميم وتحسين قواعد البيانات

    استعلامات أسرع وهيكلة أوضح وأخطاء أقل

  • تأمين المواقع والحماية المتقدمة

    حماية موقعك من التهديدات السيبرانية

  • أتمتة العمليات والمهام البرمجية

    نؤتمت المهام المتكررة ونوفّر وقتك دائمًا

لديك استفسار؟

اتصل بنا الآن

00201014714795

راسلنا عبر البريد الإلكتروني

[email protected]