Laravel İle İlişkisel Veritabanı Eloquent İlişki Kurma Nasıl Yapılır?

Laravel İle İlişkisel Veritabanı Eloquent İlişki Kurma Nasıl Yapılır?
Laravel İle İlişkisel Veritabanı Eloquent İlişki Kurma Nasıl Yapılır?

Ön Hazırlık ve Gereksinimler

Eloquent ilişkilerini uygulamaya başlamadan önce sisteminizde Laravel 11 veya üzeri bir sürümün kurulu olması önerilir. Veritabanı işlemlerini yönetmek için MySQL, PostgreSQL veya SQLite gibi bir veritabanı sürücüsünün yapılandırılmış olması gerekir.

  • PHP 8.2+ sürümü yüklü olmalıdır.
  • Composer paket yöneticisi ile Laravel projenizi oluşturmuş olmalısınız.
  • .env dosyanızda veritabanı bağlantı bilgilerinizin doğru tanımlandığından emin olun.

Projenin kök dizininde terminalinizi açarak php artisan --version komutu ile güncel sürümünüzü kontrol edebilirsiniz.

One-to-One (Bire-Bir) İlişki Kurma

Bire-bir ilişki, bir kaydın başka bir tabloda sadece bir karşılığı olduğu durumlarda kullanılır. Örneğin, bir "User" (Kullanıcı) modelinin sadece bir "Profile" (Profil) kaydı olabilir.

Öncelikle User modelinizde ilgili ilişki metodunu tanımlamalısınız. Aşağıdaki kod örneği, bir kullanıcının profile sahip olduğunu belirtir:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

class User extends Model
{
    public function profile(): HasOne
    {
        return $this->hasOne(Profile::class);
    }
}

Bu metod, Eloquent'in profiles tablosunda user_id sütununu otomatik olarak aramasını sağlar. İlişkiyi test etmek için $user->profile şeklinde veriye erişebilirsiniz.

Many-to-Many (Çok-Çok) İlişki Kurma

Çok-çok ilişkilerde, iki tablo arasında aracı bir tabloya (pivot table) ihtiyaç duyulur. Örneğin, "Post" ve "Tag" (Etiket) ilişkisi. Bir gönderinin birden fazla etiketi olabilir, bir etiket de birden fazla gönderide kullanılabilir.

Bu ilişkiyi kurmak için belongsToMany metodunu kullanırız. Aşağıdaki örnek, Post modelinde etiketleri nasıl tanımlayacağınızı gösterir:

public function tags()
{
    return $this->belongsToMany(Tag::class, 'post_tag', 'post_id', 'tag_id');
}

Burada post_tag aracı tablonun adıdır. Eğer Laravel isimlendirme standartlarına (alfabetik sıra) uyduysanız, sadece return $this->belongsToMany(Tag::class); yazmanız yeterlidir.

Eloquent İlişki Yöntemleri Karşılaştırma Tablosu

İlişki Türü Metod Kullanım Amacı
Bire-Bir hasOne / belongsTo Tekil eşleşmeler (Kullanıcı-Profil)
Bire-Çok hasMany / belongsTo Çoğul eşleşmeler (Kullanıcı-Gönderiler)
Çok-Çok belongsToMany Karmaşık ağlar (Gönderi-Etiketler)

Performans: Eager Loading (İstekli Yükleme)

Eloquent ilişkilerinde en sık yapılan hata "N+1" sorunudur. Eğer bir döngü içerisinde ilişkili verileri çekerseniz, her döngü için ayrı bir veritabanı sorgusu çalışır. Bunu engellemek için with() metodunu kullanmalısınız.

// Hatalı (N+1 sorunu yaratır)
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->comments->count();
}

// Doğru (Tek sorguda tüm ilişkili verileri çeker)
$posts = Post::with('comments')->get();
foreach ($posts as $post) {
    echo $post->comments->count();
}

Bu yöntem, uygulamanızın veritabanı yükünü ciddi oranda azaltır ve sayfa yüklenme hızını artırır.

Kritik Güvenlik Uyarısı: İlişkisel veritabanı işlemlerinde kullanıcıdan gelen verileri asla doğrudan sorguya dahil etmeyin. Laravel'in sunduğu "Query Builder" ve "Eloquent" metotları SQL Injection saldırılarına karşı koruma sağlar. Ancak, raw sorgular kullanmanız gerekiyorsa mutlaka DB::raw() veya parametre bağlama (binding) yöntemlerini tercih edin.

Sıkça Sorulan Sorular

Eloquent ilişkilerinde aracı tabloyu nasıl özelleştiririm?

belongsToMany metodunun ikinci parametresine tablonun adını, üçüncü ve dördüncü parametrelerine ise ilgili yabancı anahtar (foreign key) isimlerini vererek özelleştirebilirsiniz.

İlişkili verileri nasıl silerim?

İlişkili kayıtları silmek için delete() metodunu kullanabilirsiniz. Ancak veritabanı seviyesinde "Cascade Delete" (zincirleme silme) kullanmak, verilerin tutarlılığı açısından daha güvenlidir.

Bir modelin ilişkisi olup olmadığını nasıl kontrol ederim?

has() veya whereHas() metotlarını kullanarak, belirli bir ilişkiye sahip olan modelleri kolayca filtreleyebilirsiniz.

Pivot tablodaki verilere nasıl erişirim?

$post->tags()->withPivot('created_at')->get() şeklinde pivot tablodaki ek sütunlara erişim sağlayabilirsiniz.

Neden `belongsTo` yerine `hasOne` kullanmalıyım?

`belongsTo` yabancı anahtarın (foreign key) bulunduğu modelde kullanılır. `hasOne` ise karşı taraftaki modelde kullanılır. İlişkiyi kurarken anahtarın hangi tabloda olduğuna dikkat etmelisiniz.

Polimorfik İlişkiler ile Esnek Veri Modelleri

Standart ilişkilerin ötesine geçmek istediğinizde, Laravel'in sunduğu Polimorfik İlişkiler devreye girer. Bu yapı, bir modelin birden fazla farklı modelle tek bir ilişki üzerinden bağlanmasını sağlar. Örneğin, bir Comment (Yorum) modeliniz olduğunu ve bu yorumların hem Post (Gönderi) hem de Video modellerine ait olabileceğini düşünün.

Polimorfik İlişki Kurulumu

Bu yapıyı kurmak için veritabanınızda iki özel sütuna ihtiyacınız vardır: commentable_id (ilgili modelin ID'si) ve commentable_type (ilgili modelin sınıf ismi). Migration dosyanızda şu yapıyı kullanmalısınız:

Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->text('body');
    $table->morphs('commentable'); // commentable_id ve commentable_type oluşturur
    $table->timestamps();
});

Ardından model tarafında ilişkiyi şu şekilde tanımlarsınız:

// Comment.php
public function commentable()
{
    return $this->morphTo();
}

// Post.php
public function comments()
{
    return $this->morphMany(Comment::class, 'commentable');
}

Eloquent İlişkilerinde Hata Ayıklama ve Sorgu İzleme

İlişkiler karmaşıklaştıkça, Eloquent'in arka planda hangi SQL sorgularını çalıştırdığını görmek hata ayıklama sürecini hızlandırır. Laravel'in DB::enableQueryLog() özelliğini kullanarak ilişkilerinizin veritabanını nasıl yorduğunu analiz edebilirsiniz.

Sorgu Günlüğünü Kullanma

Geliştirme aşamasında bir rotada veya test sınıfında şu yöntemi kullanarak ilişkilerinizin performansını ölçebilirsiniz:

\DB::enableQueryLog();

$posts = Post::with('comments')->get();

dd(\DB::getQueryLog());

Bu çıktı size kaç adet sorgu çalıştığını ve bu sorguların ne kadar sürdüğünü gösterir. Eğer N+1 problemi yaşıyorsanız, with() metodunun doğru çalışıp çalışmadığını bu günlükler üzerinden kolayca tespit edebilirsiniz. Unutmayın, ilişkilerinizde lazy loading (tembel yükleme) yerine eager loading (istekli yükleme) kullanmak, veritabanı yükünüzü %80'e varan oranlarda azaltabilir.

İleri İpucu: İlişki Sorgularını Filtreleme

Bazen sadece belirli koşulları sağlayan ilişkili verileri çekmek istersiniz. Örneğin, sadece onaylanmış yorumları getirmek için ilişki tanımlamanızda şu filtrelemeyi kullanabilirsiniz:

public function approvedComments()
{
    return $this->hasMany(Comment::class)->where('is_approved', true);
}

Bu yöntem, ilişkili verileri ana model üzerinden çekerken ekstra bir where sorgusu yazmanıza gerek kalmadan, doğrudan $post->approvedComments şeklinde temiz bir kullanım sağlar.

Sonuç

Laravel ile ilişkisel veritabanı Eloquent ilişki kurma işlemleri, uygulama mimarinizi temiz ve sürdürülebilir kılmak için temel bir beceridir. Bu rehberde öğrendiğiniz hasOne, hasMany ve belongsToMany metotları, çoğu projenin omurgasını oluşturur. Bir sonraki adım olarak, "Polymorphic Relationships" (Polimorfik İlişkiler) konusunu inceleyerek, tek bir modelin birden fazla farklı modelle nasıl ilişki kurabileceğini öğrenebilirsiniz.

Kod güvenliğiniz için her zaman güncel Laravel dokümantasyonunu takip edin ve uygulamalarınızı üretim (production) ortamına almadan önce tüm ilişkilerinizi birim testleri (unit tests) ile doğrulayın.

Bu yazıya tepkinizi paylaşın:
Mert Demir

Teknik beceriler ve bakım onarım rehberleri konusunda deneyimli bir editörüm. Okuyucularıma günlük hayatta tasarruf sağlayacak ipuçları sunuyorum.

Yorumlar (0)

Yorum Yaz