Gereksinimler ve Ön Hazırlık
Laravel ile çalışırken veritabanı ilişkilerini yönetmek için sisteminizde PHP 8.2 veya üzeri bir sürümün, Composer paket yöneticisinin ve Laravel 11/12 güncel sürümünün yüklü olması gerekmektedir. Ayrıca veritabanı sürücüsü olarak MySQL, PostgreSQL veya SQLite kullanabilirsiniz.
- PHP 8.2+: Modern sözdizimi desteği için gereklidir.
- Composer: Bağımlılık yönetimi için zorunludur.
- Veritabanı İstemcisi: TablePlus, DBeaver veya phpMyAdmin gibi bir araç, ilişkileri görselleştirmenize yardımcı olur.
Projenizin kök dizininde bulunan .env dosyasının veritabanı bağlantı bilgilerinizin doğru yapılandırıldığından emin olun. Hatalı bağlantılar, migration (göç) işlemlerinin başarısız olmasına neden olur.
Migration ile Tablo Yapılarını Oluşturma
Laravel'de veritabanı şeması, "migration" dosyaları ile yönetilir. İlişkisel bir model kurmadan önce, tablolar arasındaki anahtar (key) bağlantılarını tanımlamamız gerekir. Bir "Kullanıcı" (User) ve onun "Yazıları" (Post) olduğunu varsayalım. Bu, tipik bir bire-çok (one-to-many) ilişkisidir.
// posts tablosu için migration dosyası
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
Burada kullanılan foreignId metodu, user_id sütununu oluşturur ve constrained metodu ile users tablosundaki id sütununa referans verir. onDelete('cascade') komutu ise, bir kullanıcı silindiğinde ona ait tüm yazıların da otomatik olarak silinmesini sağlar; bu, veri bütünlüğü için kritik bir güvenlik önlemidir.
Eloquent ORM ile İlişkileri Tanımlama
Model sınıflarınızda ilişkileri tanımlamak, Laravel'in sihirli gücünü ortaya çıkarır. İlişkiyi tanımladığınızda, verileri sanki bir nesnenin özelliğiymiş gibi çağırabilirsiniz. User modeli içerisinde bir kullanıcının yazılarına erişmek için hasMany metodunu kullanırız.
// app/Models/User.php
public function posts()
{
return $this->hasMany(Post::class);
}
// app/Models/Post.php
public function user()
{
return $this->belongsTo(User::class);
}
Bu tanımlamalar sayesinde, $user->posts dediğinizde Laravel arka planda SQL sorgusunu otomatik olarak oluşturur. belongsTo metodu ise, yazının hangi kullanıcıya ait olduğunu belirlemek için ters ilişkiyi kurar.
İlişkisel Veri Sorgulama ve Eager Loading
Veritabanı sorgularında en sık yapılan hata "N+1" problemidir. Bir döngü içerisinde her yazı için tekrar tekrar kullanıcı sorgusu yapmak, uygulamanızı yavaşlatır. Bunun yerine "Eager Loading" (istekli yükleme) yöntemini kullanmalıyız.
// N+1 probleminden kaçınmak için
$posts = Post::with('user')->get();
foreach ($posts as $post) {
echo $post->user->name;
}
with('user') metodu, tüm yazıları ve onlara ait kullanıcıları tek bir sorguda (JOIN ile) veya optimize edilmiş iki sorguda getirir. Bu, veritabanı üzerindeki yükü ciddi oranda azaltır ve uygulamanın yanıt süresini iyileştirir.
Çoktan Çoğa İlişkiler ve Pivot Tablolar
Örneğin, bir yazının birden fazla etiketi (tag) olabilir ve bir etiket birden fazla yazıda kullanılabilir. Bu durumda "many-to-many" ilişkisi kullanılır. Bunun için bir ara tabloya (pivot table) ihtiyacımız vardır.
// Pivot tablo migration'ı
Schema::create('post_tag', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->foreignId('tag_id')->constrained()->onDelete('cascade');
});
Model içerisinde ise belongsToMany metodunu kullanırız. Bu yapı, karmaşık verileri yönetmek için en esnek yöntemdir.
// Post modelinde
public function tags()
{
return $this->belongsToMany(Tag::class);
}
İlişki Türleri Karşılaştırma Tablosu
| İlişki Türü | Eloquent Metodu | Kullanım Amacı |
|---|---|---|
| Bire-Bir | hasOne / belongsTo | Profil bilgileri gibi tekil eşleşmeler. |
| Bire-Çok | hasMany / belongsTo | Bir kullanıcının birden fazla gönderisi olması. |
| Çoktan-Çoğa | belongsToMany | Kategoriler veya etiketler sistemi. |
Kritik Güvenlik Uyarısı: Veritabanı ilişkilerinde onDelete('cascade') kullanırken dikkatli olun. Yanlışlıkla bir ana veriyi silmek, ilişkili tüm verilerin kalıcı olarak kaybolmasına yol açabilir. Üretim ortamında (production) bu tür işlemleri yapmadan önce mutlaka veritabanı yedeği alın ve "soft delete" (yumuşak silme) yöntemini değerlendirin.
Sıkça Sorulan Sorular
Eloquent ilişkilerinde neden 'id' yerine farklı bir sütun kullanamıyorum?
Laravel varsayılan olarak id sütununu anahtar olarak kabul eder. Eğer özel bir sütun kullanıyorsanız, hasMany metodunun ikinci ve üçüncü parametrelerinde bu sütunları açıkça belirtmeniz gerekir.
İlişkili verileri nasıl filtrelerim?
whereHas metodunu kullanarak, ilişkili tablodaki kriterlere göre ana tablodaki verileri filtreleyebilirsiniz. Örneğin: Post::whereHas('tags', function($q) { $q->where('name', 'Laravel'); })->get();
Pivot tablolarda ek veriler nasıl tutulur?
withPivot metodunu kullanarak ara tablodaki ek sütunlara (örneğin: created_at veya role) erişebilirsiniz.
İlişki kurarken 'constrained' kullanmak zorunlu mu?
Zorunlu değildir ancak veritabanı seviyesinde veri bütünlüğünü (referential integrity) garanti altına almak için kesinlikle önerilir.
Performans için ilişkilerde index kullanmalı mıyım?
Evet, foreignId ile oluşturduğunuz tüm sütunlara veritabanı seviyesinde index eklemek, sorgu hızını ciddi oranda artırır. Laravel bunu otomatik olarak optimize etmeye çalışsa da, büyük veri setlerinde manuel kontrol önemlidir.
İleri Seviye İlişki Teknikleri ve Polimorfik İlişkiler
Standart "bire-çok" veya "çoktan-çoğa" ilişkilerin ötesine geçmek istediğinizde, Laravel'in sunduğu Polimorfik İlişkiler hayat kurtarıcıdır. Bu yapı, tek bir modelin birden fazla farklı modelle ilişkilendirilmesine olanak tanır. Örneğin, hem Post hem de Video modellerine yorum yapılabilen bir sistem tasarladığınızı varsayalım.
Polimorfik bir ilişki kurmak için veritabanında commentable_id ve commentable_type sütunlarına ihtiyaç duyarsınız. İşte bunu tanımlamanın yolu:
// Migration dosyanızda
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('body');
$table->morphs('commentable'); // commentable_id ve commentable_type oluşturur
$table->timestamps();
});
// Model içerisinde ilişki tanımı
class Comment extends Model {
public function commentable() {
return $this->morphTo();
}
}
class Post extends Model {
public function comments() {
return $this->morphMany(Comment::class, 'commentable');
}
}
İlişkisel Veri Sorgularında Hata Ayıklama ve Debugging
Karmaşık ilişkilerde bazen beklediğiniz sonuçları alamayabilirsiniz. Laravel'in toSql() yöntemi, Eloquent tarafından oluşturulan ham SQL sorgusunu görmenizi sağlar. Bu, özellikle whereHas veya with kullanırken oluşan hataları ayıklamak için en etkili yöntemdir.
Sorgularınızın veritabanına nasıl gittiğini görmek için aşağıdaki yöntemi kullanabilirsiniz:
$query = User::whereHas('posts', function($q) {
$q->where('status', 'published');
});
// Sorguyu ekrana yazdır ve durdur
dd($query->toSql(), $query->getBindings());
Ayrıca, Laravel Debugbar paketi, ilişkisel sorguların kaç kez çalıştığını (N+1 problemi) ve her bir sorgunun ne kadar sürdüğünü görselleştirmek için geliştirme sürecinde mutlaka kullanılmalıdır.
İlişkilerde Veri Bütünlüğünü Koruma (Cascading Deletes)
İlişkili veriler silindiğinde, veritabanında "yetim" (orphan) kayıtlar kalabilir. Laravel migration'larında onDelete('cascade') kullanarak, ana kayıt silindiğinde ilişkili tüm alt kayıtların otomatik olarak silinmesini sağlayabilirsiniz.
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')
->constrained()
->onDelete('cascade'); // Kullanıcı silinirse postları da silinir
});
Bu yaklaşım, uygulama katmanında (PHP tarafında) silme işlemi yapmaktan çok daha güvenlidir çünkü veritabanı seviyesinde tutarlılığı garanti eder.
Sonuç
Laravel ile ilişkisel veritabanı modeli oluşturmak, verilerinizi düzenli tutmanın ve uygulamanızın performansını artırmanın en iyi yoludur. Migration ile şemayı tanımlamak, Eloquent ile ilişkileri kurmak ve Eager Loading ile sorguları optimize etmek, profesyonel bir Laravel geliştiricisinin temel yetenekleridir. Bir sonraki adım olarak, veritabanı işlemlerinizi daha güvenli hale getirmek için "Database Transactions" (Veritabanı İşlemleri) konusunu araştırmanızı öneririm.
Sorumluluk Reddi: Bu rehber yazılım geliştirme eğitimi amaçlıdır. Veritabanı işlemleri yapmadan önce her zaman geliştirme ortamında test yapın ve canlı veritabanlarında işlem yapmadan önce mutlaka yedek alın.


Yorumlar (0)
Yorum Yaz