#004: Laravel’da Query Scope Kullanımıyla Tekrardan Kurtulun ve Sürdürülebilir Kod Yazın!

Erhan ÜRGÜNErhan ÜRGÜN
2 min read

Küçük görünen tekrarlar, büyüdükçe yönetilemez hale gelir. Sizin kodunuzda tekrar eden sorgular var mı, yoksa her şey kontrolünüz altında mı?

Birçok geliştirici, Eloquent sorgularında benzer filtreleri defalarca yazmaktan bıkmıştır. Tekrarlayan koşullar, hem kodun okunabilirliğini hem de bakımını zorlaştırır. Üstelik ileride filtrelerde bir değişiklik olursa, projenin farklı yerlerinde aynı güncellemeleri tekrar tekrar yapmak zorunda kalırsınız.

Bu kısır döngüden çıkmanın en etkili yolu Query Scope’ları kullanmaktır!

Scope’lar sadece kod tekrarını önlemekle kalmaz; kodunuza anlam katar, standartlaştırır ve takım içi iş birliğini kolaylaştırır. Büyük ölçekli projelerde, ortak kullanılan filtrelerin tek noktadan yönetilmesi, hata oranını ciddi şekilde azaltır.

Sadece sabit koşullar için değil, parametreli scope’lar ile çok daha esnek sorgular üretebilirsiniz.

Örnek: Yayınlanma tarihiyle filtreleme

// Path: app/Models/Post.php
public function scopePublishedAfter($query, $date)
{
    return $query->where('published_at', '>', $date);
}

// Kullanımı:
$recentPosts = Post::active()->publishedAfter(now()->subDays(7))->get();

Scope’lar birbiriyle zincirlenebilir. Böylece birbirinden bağımsız, anlamlı filtreleri kolayca kombine edebilirsiniz.

// Path: app/Models/Post.php
public function scopePopular($query)
{
    return $query->where('views', '>', 1000);
}

// Kullanımı:
$posts = Post::active()->popular()->publishedAfter('2025-01-01')->get();

Bazı filtrelerin her zaman ve her yerde uygulanmasını istiyorsanız, global scope kullanarak modelinize otomatik davranışlar kazandırabilirsiniz.

// Path: app/Models/Post.php
protected static function booted()
{
    static::addGlobalScope('notDeleted', function ($query) {
        $query->whereNull('deleted_at');
    });
}

Artık tüm Post sorgularınızda deleted_at otomatik olarak filtrelenir.

Tekrar eden string değerler yerine enum kullanarak kodunuzu hem okunur hem hatasız hâle getirin.

// Path: app/Enums/StatusEnum.php
class StatusEnum extends BaseEnum
{
    public const DEFAULT = self::ACTIVE;
    public const ACTIVE = 'active';
    public const PASSIVE = 'passive';
    // ...
}

// Path: app/Models/Post.php
public function scopeActive($query)
{
    return $query->where('status', StatusEnum::ACTIVE)->whereNull('deleted_at');
}

// Path: app/Http/Controllers/Api/PostController.php
$activePosts = Post::active();

Veya bu şekilde bir kullanım ile:

// Path: app/Enums/StatusEnum.php
enum StatusEnum: string
{
    case ACTIVE = 'active';
    case PASSIVE = 'passive';
}

// Path: app/Models/Post.php
public function scopeStatus($query, StatusEnum $status)
{
    return $query->where('status', $status->value);
}

// Kullanımı:
$activePosts = Post::status(StatusEnum::ACTIVE)->get();

❌ Tekrarlı, okunmaz ve bakım maliyetli kod:

// Path: app/Http/Controllers/Api/PostController.php
$posts = Post::where('status', 'active')
    ->where('views', '>', 1000)
    ->whereNull('deleted_at')
    ->where('published_at', '>', now()->subMonth())
    ->get();

✅ Temiz, okunabilir, sürdürülebilir kod:

// Path: app/Http/Controllers/Api/PostController.php
$posts = Post::active()->popular()->publishedAfter(now()->subMonth())->get();

Siz projelerinizde scope’ları nasıl kullanıyorsunuz? Parametreli scope, global scope ya da enum ile birlikte scope kullanımında farklı yaklaşımlarınız var mı? Kodunuzun sürdürülebilirliğini artırmak için başka hangi yöntemleri tercih ediyorsunuz?

Fikirlerinizi ve deneyimlerinizi paylaşarak topluluğa katkı sağlayın!


Daha fazla temiz kod, Laravel ve profesyonel yazılım ipucu için takipte kalın:

0
Subscribe to my newsletter

Read articles from Erhan ÜRGÜN directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Erhan ÜRGÜN
Erhan ÜRGÜN

Laravel | AdonisJS | Back-End Developer