Laravel Macro ve Koleksiyon İpuçları Rehberi

## Laravel Macro ve Koleksiyon İpuçları: Uygulanabilir Bir Rehber Laravel'de uygulama kodunuzun büyük bölümü, çerçevenin sunduğu sınıflara eklediğini...

Laravel Macro ve Koleksiyon İpuçları Rehberi

Laravel Macro ve Koleksiyon İpuçları: Uygulanabilir Bir Rehber

Laravel'de uygulama kodunuzun büyük bölümü, çerçevenin sunduğu sınıflara eklediğiniz küçük yardımcı davranışlarla şekillenir. Macro mekanizması ve koleksiyon API'si bu noktada en çok işe yarayan iki araçtır: biri mevcut sınıfları genişletmenizi, diğeri veri kümelerini okunabilir bir akış içinde işlemenizi sağlar. Bu rehber, orta seviye bir Laravel geliştiricisinin bu iki konuyu günlük iş akışına nasıl dahil edebileceğine odaklanır.

Önkoşul olarak temel Laravel bilgisi, service provider kavramı ve PHP closure mantığına aşinalık yeterlidir. Sürüm kapsamı açısından macro ve koleksiyon API'leri Laravel'in uzun süredir korunan temel özellikleridir; burada anlatılan yaklaşımlar belirli bir sürüm numarasına bağlanmadan geçerliliğini korur. Yine de kendi projenizde davranışı doğrulamadan üretime almamanızı öneririm.

Macro Nedir, Nerede Tanımlanır

Macro, Laravel'in Macroable trait'ini kullanan sınıflara çalışma zamanında yeni metot eklemenizi sağlar. Collection, Str, Arr, Request, Response, Route gibi sınıflar bu trait'i kullanır.

Tanımların uygulama açılışında bir kez yapılması gerekir. Bunun için tipik yer bir service provider'ın boot metodudur:

use Illuminate\Support\Collection;
use Illuminate\Support\Str;

public function boot(): void
{
    Collection::macro('toUpper', function () {
        return $this->map(fn ($value) => Str::upper($value));
    });
}

Bu tanımdan sonra herhangi bir koleksiyon üzerinde ->toUpper() çağırabilirsiniz. Macro içindeki $this, macro'nun çağrıldığı koleksiyon örneğidir; bu sayede zincirin geri kalanıyla doğal biçimde bütünleşir.

Macro'ları dağınık biçimde birden fazla provider'a yaymak yerine tek bir MacroServiceProvider altında toplamak, ileride hangi özel metodun nereden geldiğini takip etmeyi kolaylaştırır.

Koleksiyonlarda Sık Kullanılan Yardımcılar

Laravel koleksiyonları, dizilerle çalışırken tekrar eden döngülerin çoğunu ortadan kaldırır. Aşağıdaki metotlar günlük işlerde en çok fark yaratanlardır.

map, filter ve zincirleme

$names = collect([1, 2, 3, 4])
    ->filter(fn ($n) => $n % 2 === 0)
    ->map(fn ($n) => "ürün-{$n}")
    ->values();

filter sonrası anahtarlar korunur. Sıralı bir dizi bekliyorsanız values() çağırmayı unutmayın; aksi halde JSON çıktısında dizi yerine nesne görürsünüz. Bu, en sık karşılaşılan hatalardan biridir.

groupBy ve keyBy

$orders = collect([
    ['user_id' => 1, 'total' => 100],
    ['user_id' => 2, 'total' => 250],
    ['user_id' => 1, 'total' => 75],
]);

$byUser = $orders->groupBy('user_id');
$indexed = $orders->keyBy('user_id');

groupBy her anahtar için bir alt koleksiyon döndürürken, keyBy her kaydı tek bir anahtarla eşler. keyBy kullandığınızda aynı anahtara sahip birden fazla kayıt varsa son kaydın kazandığını bilmeniz gerekir; bu sessiz veri kaybına yol açabilir.

pluck, unique ve sortBy

$emails = $users->pluck('email')->unique()->values();
$sorted = $users->sortByDesc('created_at');

sortBy yeni bir koleksiyon döndürür, orijinali değiştirmez. Koleksiyonların çoğu metodu değişmez (immutable) davranış sergiler; sonucu bir değişkene atamayı ihmal ederseniz değişiklik kaybolur.

when ile koşullu zincirleme

$query = collect($items)
    ->when($onlyActive, fn ($c) => $c->where('active', true))
    ->when($limit, fn ($c) => $c->take($limit));

when, koşula bağlı olarak koleksiyonu dönüştürmenizi sağlar. if bloklarıyla zinciri bölmek yerine okunabilir bir akış elde edersiniz.

Koleksiyon Macro'ları ile Tekrarı Azaltmak

Projeye özgü iş mantığını koleksiyon macro'su olarak tanımlamak, aynı dönüşümü farklı yerlerde tekrar yazma ihtiyacını ortadan kaldırır.

Collection::macro('toSelectOptions', function (string $labelKey, string $valueKey) {
    return $this->map(fn ($item) => [
        'label' => data_get($item, $labelKey),
        'value' => data_get($item, $valueKey),
    ])->values();
});

Kullanımı:

$options = $users->toSelectOptions('name', 'id');

Bu tür macro'lar özellikle form seçenekleri, dropdown verileri ve API yanıtları üretirken kodu kısaltır. Macro içinde data_get kullanmak, hem dizi hem nesne girdilerini aynı kodla işlemenizi sağlar.

String ve Diğer Sınıflarda Macro

Str sınıfı da macro'ları destekler ve metin dönüşümlerini merkezileştirmek için uygundur:

Str::macro('slugTr', function (string $value) {
    return Str::slug(Str::ascii($value));
});

Burada dikkat edilmesi gereken nokta, Str::ascii'nin Türkçe karakterleri nasıl dönüştürdüğünü kendi girdilerinizle test etmenizdir; beklenmeyen eşlemeler üretimde slug çakışmalarına yol açabilir.

Yaygın Hatalar ve Dikkat Edilmesi Gerekenler

  • Macro'yu geç tanımlamak: Macro'lar boot aşamasında kaydedilmelidir. Route dosyası veya bir controller içinde tanımlamak, o noktaya kadar çalışan kodda metodun bulunmamasına yol açar.
  • Ad çakışması: Bir macro'nun adı, çerçevenin ileride ekleyebileceği bir metotla çakışabilir. Bu, yükseltme sırasında beklenmeyen davranışa neden olur. Projeye özgü, açık isimler tercih edin.
  • values() unutmak: filter, sortBy, unique gibi metotlardan sonra sıralı dizi bekliyorsanız values() çağırın.
  • Büyük koleksiyonlarda bellek: collect() tüm veriyi belleğe alır. Milyonlarca satırla çalışıyorsanız LazyCollection (cursor, lazy) kullanmayı değerlendirin.
  • Yan etki beklemek: Koleksiyon metotlarının çoğu yeni bir koleksiyon döndürür. Sonucu kullanmadığınız sürece hiçbir şey değişmez.

Güvenlik Notları

Macro'lar ve koleksiyon metotları, girdi doğrulaması veya yetkilendirme yerine geçmez. Kullanıcıdan gelen veriyi doğrudan data_get veya pluck ile işlemek, beklenmeyen anahtarların sızmasına yol açabilir. Özellikle API yanıtı üretirken yalnızca ihtiyaç duyulan alanları only veya map ile seçin; tüm model alanlarını toArray ile dışarı vermek hassas verileri açığa çıkarır.

Macro içinde kullanıcı girdisini SQL veya dosya yolu gibi bağlamlara aktarıyorsanız, ilgili katmanın kendi koruma mekanizmalarına (query binding, path doğrulama) güvenmeniz gerekir. Macro kullanmak bu korumaları otomatik olarak sağlamaz.

Sonuç

Macro'lar, çerçeve sınıflarını projeye özgü davranışlarla genişletmenin hafif bir yoludur; koleksiyon API'si ise veri dönüşümlerini okunabilir bir akışa çevirir. İkisini birlikte kullanmak, tekrar eden döngüleri ve dağınık if bloklarını azaltır. Kritik nokta, macro'ları merkezi bir provider'da toplamak, dönüş değerlerini kullanmayı ihmal etmemek ve koleksiyon metotlarının değişmez davranışını akılda tutmaktır. Bu alışkanlıklar, kod tabanınız büyüdükçe tutarlılığı korumanıza yardımcı olur.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz