İçeriğe geç
Muhammet Şafak
Framework & Kütüphane 4 dk okuma

Eloquent ORM ile veritabanı işlemlerini sadeleştirmek

SQL'i elle yazmaktan model tabanlı erişime: Laravel Eloquent ORM'in uygulama tarafından görünümü ve günlük kullanımı.


Laravel’e geçmeden önce veritabanı işlemlerimi çoğunlukla elle SQL yazarak yapıyordum. mysqli_query() ile başlayıp zamanla PDO’ya geçmiştim; ama her sorguda prepare, bindParam, execute döngüsü yazıyordum. Bu hem tekrarlayan hem de hataya açık bir işti.

Laravel’de Eloquent ORM bunu farklı bir yerden ele alıyor. Bir aydan biraz fazladır kullanıyorum; günlük işlemlerde farkı belirgin.

ORM nedir?

ORM (Object-Relational Mapper), veritabanı tablolarını uygulama tarafında nesneler olarak temsil eden katmandır. Tabloyla konuşmak yerine bir PHP nesnesiyle çalışıyorsunuz; ORM sorgu işini hallediyor.

Eloquent, Laravel’in bu katmanı. Her veritabanı tablosu için bir model sınıfı (model class) tanımlıyorsunuz.

Model tanımlamak

app/models/Kullanici.php:

<?php

class Kullanici extends Eloquent
{
    protected $table = 'kullanicilar';
}

Bu kadar. $table özelliğini yazmazsanız Eloquent tablo adını sınıf adından otomatik türetiyor: Kullanicikullanicis (İngilizce çoğul kuralıyla). Türkçe tablo isimleri kullanıyorsanız açıkça belirtmek daha güvenli.

Kayıt okumak

// Tüm kullanıcılar
$kullanicilar = Kullanici::all();

// ID'ye göre tek kayıt
$kullanici = Kullanici::find(1);

// Koşullu sorgu
$aktifler = Kullanici::where('durum', '=', 'aktif')->get();

// İlk eşleşen kayıt
$yonetici = Kullanici::where('rol', 'admin')->first();

all(), find(), where() gibi metotlar SQL sorgusunu arka planda oluşturuyor. Siz PHP metotlarıyla çalışıyorsunuz.

Kayıt oluşturmak ve güncellemek

// Yeni kayıt
$kullanici = new Kullanici();
$kullanici->ad = 'Ahmet';
$kullanici->email = '[email protected]';
$kullanici->save();

// Ya da tek satırda create() ile (mass assignment koruması etkin olmalı)
Kullanici::create([
    'ad' => 'Mehmet',
    'email' => '[email protected]'
]);

// Güncelleme
$kullanici = Kullanici::find(5);
$kullanici->email = '[email protected]';
$kullanici->save();

create() metodunu kullanırken modelde $fillable özelliğini belirtmek gerekiyor; bu, hangi alanların toplu atamaya açık olduğunu tanımlar:

class Kullanici extends Eloquent
{
    protected $table = 'kullanicilar';
    protected $fillable = ['ad', 'email'];
}

$fillable listesine almadığınız bir alan, kullanıcı verisinden doğrudan geçirilse bile kaydedilmiyor. Bu, bir form alanına rol=admin ekleyerek kullanıcı rolünü değiştirmeye çalışan saldırıları engelleyen basit ama önemli bir koruma. $guarded = [] yazarak tüm alanları açmak da mümkün, ama başlangıçta kapalı tutup gerektiğini eklemek daha güvenli bir alışkanlık.

Kayıt silmek

$kullanici = Kullanici::find(3);
$kullanici->delete();

// Ya da doğrudan
Kullanici::destroy(3);

Sorgu zinciri

Eloquent’in güzel taraflarından biri metotları zincir halinde kullanmak:

$sonuc = Kullanici::where('durum', 'aktif')
    ->orderBy('olusturuldu_at', 'desc')
    ->take(10)
    ->get();

Bu kod, aktif kullanıcıları en yeniden eskiye doğru sıralayıp ilk 10’unu getiriyor. SQL yazarken bu sorgu daha uzun ve hata olasılığı daha yüksek olurdu.

İlişkiler (Relationships)

Tablolar arası ilişkileri model düzeyinde tanımlamak Eloquent’in güçlü alanlarından. Şimdilik basit bir örnek:

class Kullanici extends Eloquent
{
    public function yorumlar()
    {
        return $this->hasMany('Yorum');
    }
}

class Yorum extends Eloquent
{
    public function kullanici()
    {
        return $this->belongsTo('Kullanici');
    }
}

Bu tanımlardan sonra:

$kullanici = Kullanici::find(1);
$yorumlar = $kullanici->yorumlar; // o kullanıcının tüm yorumları

$yorum = Yorum::find(10);
$yazanKisi = $yorum->kullanici; // yorumu yazan kullanıcı

İlişkili verilere özellik (property) erişimi gibi ulaşıyorsunuz; arka planda JOIN sorgusu çalışıyor.

firstOrCreate ve updateOrCreate

Günlük çalışmada sıkça karşılaştığım iki metot var: bir kaydın zaten var olup olmadığını kontrol etmek, yoksa oluşturmak. Bu işi elle yapmak şöyle görünüyor:

// Elle: önce ara, bulamazsan oluştur
$kullanici = Kullanici::where('email', $email)->first();
if (!$kullanici) {
    $kullanici = Kullanici::create(['email' => $email, 'ad' => $ad]);
}

Eloquent’in firstOrCreate metodu bunu tek satıra indiriyor:

$kullanici = Kullanici::firstOrCreate(
    ['email' => $email],       // Arama kriteri
    ['ad' => $ad]              // Bulunamazsa eklenecek alanlar
);

updateOrCreate ise kaydı bulamazsa oluşturuyor, bulursa güncelliyor. İçe aktarma (import) işlemlerinde veya dış servislerden gelen verilerle çalışırken çok işe yarıyor.

Dikkat ettiğim nokta

ORM kullanmak SQL bilgisini gereksiz kılmıyor. Arka planda ne tür sorgular üretildiğini bilmek önemli. Özellikle ilişkili verileri döngüde çekerken N+1 sorgu sorununa dikkat etmek gerekiyor.

N+1 sorunu şöyle oluşuyor: 10 kullanıcıyı çekiyorsunuz (1 sorgu), sonra her kullanıcının yorumlarını ayrı ayrı çekiyorsunuz (10 sorgu daha) — toplamda 11 sorgu. Kullanıcı sayısı 100 olunca 101 sorgu oluyor ve sayfa yavaşlıyor.

Bu sorunun çözümü için Eloquent’in with() metodu var: ilişkili veriyi tek sorguda önceden yüklemek (eager loading). O ayrı bir konu; ama ilişkileri kullanmaya başladığınızda bu kavramı öğrenmek kaçınılmaz oluyor.

Şimdilik Eloquent günlük işlemlerde elle SQL yazmaktan çok daha az yorucu. Modeli tanımlayınca geri kalanı akıyor.

ORM kullanırken bir noktada “gerçek SQL nerede yazılıyor?” sorusu geliyor. Laravel’de DB::listen() veya dd(DB::getQueryLog()) ile Eloquent’in ürettiği sorguları görebiliyorsunuz. Geliştirme ortamında bunu açık tutmak, performans sorunlarını erken fark etmek için iyi bir alışkanlık. Bir sorguda beklenmedik sayıda JOIN veya alt sorgu görürsünüz ve modeli nasıl kurduğunuzu yeniden düşünürsünüz. ORM sizi SQL’den soyutlar, ama gerçekten saygı duyduğunuzda soyutlamanın altını anlamak istersiniz.

Etiketler: #Laravel
Paylaş:

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi