Gereksinimler ve Ön Hazırlık
Başarılı bir içerik öneri motoru geliştirmek için standart bir Laravel kurulumuna ek olarak veritabanı tasarımınızın "ilişkisel" (relational) olması gerekir. Kullanıcıların içeriklerle nasıl etkileşime girdiğini takip etmek için bir "etkileşim" (interaction) tablosuna ihtiyacımız var.
- PHP 8.2+ ve Laravel 11+ sürümü.
- MySQL veya PostgreSQL üzerinde çalışan bir veritabanı.
- Kullanıcıların içeriklere verdiği puanları veya görüntüleme sayılarını tutacak bir yapı.
- Redis (Opsiyonel ancak önerilen: Önbellekleme ve hızlı veri okuma için).
Veritabanı Şeması ve Etkileşim Takibi
Öneri motorunun kalbi, kullanıcıların hangi içeriklere ilgi duyduğunu kaydeden verilerdir. "Interaction" adında bir tablo oluşturarak kullanıcının içeriğe olan ilgisini (okuma, beğenme, tıklama) puanlayacağız.
// Migration dosyası: create_interactions_table
Schema::create('interactions', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->unsignedTinyInteger('score'); // 1: görüntüleme, 5: beğenme
$table->timestamps();
});
Bu tablo, her kullanıcı için bir "ilgi profili" oluşturmamıza olanak tanır. Örneğin, bir kullanıcı teknoloji kategorisindeki bir içeriğe 5 puan verirse, bu kullanıcının teknolojiye olan ilgisi artmış olur.
İlgi Alanı Analizi ve Kullanıcı Profili Oluşturma
Kullanıcının hangi kategorilere ilgi duyduğunu hesaplamak için Eloquent ilişkilerini kullanacağız. Kullanıcının en çok etkileşime girdiği kategorileri bulmak, öneri motorunun temelidir.
// User.php model dosyası
public function getTopCategories()
{
return $this->interactions()
->join('posts', 'interactions.post_id', '=', 'posts.id')
->select('posts.category_id', DB::raw('SUM(score) as total_score'))
->groupBy('posts.category_id')
->orderBy('total_score', 'desc')
->limit(3)
->get();
}
Bu metod, kullanıcının geçmiş etkileşimlerine bakarak en yüksek puanlı 3 kategoriyi döndürür. Bu veriyi, öneri motorumuzun ana filtresi olarak kullanacağız.
Dinamik Öneri Algoritması Geliştirme
Öneri motoru, kullanıcının ilgi duyduğu kategorilerden, daha önce görmediği içerikleri çekmelidir. İşte Laravel ile yazılmış temel bir öneri mantığı:
// RecommendationService.php
public function getRecommendations(User $user)
{
$topCategories = $user->getTopCategories()->pluck('category_id');
return Post::whereIn('category_id', $topCategories)
->whereNotIn('id', $user->interactions->pluck('post_id'))
->inRandomOrder()
->limit(10)
->get();
}
Bu kod bloğu, kullanıcının sevdiği kategorilerden rastgele 10 içerik seçer ancak kullanıcının zaten okuduğu içerikleri hariç tutar. Bu, kullanıcıya her zaman "taze" içerik sunulmasını sağlar.
Performans ve Ölçeklendirme Stratejileri
Öneri motorları veritabanını yoğun bir şekilde sorgular. Binlerce kullanıcınız olduğunda, her sayfada bu sorguyu çalıştırmak veritabanını yorar. Redis kullanarak önerileri önbelleğe almalısınız.
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Gerçek Zamanlı Sorgu | En güncel veriyi sunar. | Veritabanı yükü yüksektir. |
| Redis Önbellekleme | Çok hızlı yanıt verir. | Veriler anlık olmayabilir. |
Güvenlik Uyarısı: Kullanıcı etkileşim verilerini işlerken SQL Injection riskine karşı her zaman Eloquent veya Query Builder kullanın. Ham SQL sorguları yazmaktan kaçının.
Sıkça Sorulan Sorular
Öneri motoru soğuk başlangıç (cold start) problemini nasıl çözer?
Henüz etkileşimi olmayan yeni kullanıcılar için, genel olarak en çok beğenilen veya en yeni içerikleri "popüler içerikler" olarak varsayılan öneri listesi şeklinde sunabilirsiniz.
Önerileri ne sıklıkla güncellemeliyim?
Kullanıcı etkileşimine bağlı olarak, Laravel Job (iş kuyruğu) kullanarak her 1 saatte bir veya kullanıcı her 5 etkileşimde bir öneri listesini arka planda güncelleyebilirsiniz.
Redis kullanmak zorunlu mu?
Küçük ölçekli projelerde zorunlu değildir ancak 10.000+ kullanıcıya ulaştığınızda veritabanı performansını korumak için kesinlikle önerilir.
Kullanıcı gizliliği için ne yapmalıyım?
Kullanıcıların hangi içeriklere tıkladığını anonimleştirerek tutun ve KVKK/GDPR uyumluluğu için "kişiselleştirilmiş önerileri kapat" seçeneği sunun.
Daha gelişmiş öneriler için ne kullanabilirim?
İlerleyen aşamalarda Laravel ile entegre çalışan yapay zeka servisleri veya vektör tabanlı veritabanları (Pinecone, Milvus gibi) kullanarak içerik benzerliği analizi yapabilirsiniz.
Öneri Motoru İçin Birim ve Entegrasyon Testleri
Öneri motorunuzun kararlılığını sağlamak, özellikle kullanıcı davranışlarına göre dinamik sonuçlar ürettiğinizde kritik öneme sahiptir. Yanlış bir algoritma mantığı, kullanıcıya tamamen alakasız içerikler sunmanıza neden olabilir. Laravel'in yerleşik PHPUnit desteği ile öneri motorunuzu test etmek için aşağıdaki yaklaşımı izleyebilirsiniz.
Öncelikle, belirli bir kullanıcının etkileşim geçmişine göre öneri döndüren metodunuzu test eden bir birim testi oluşturalım:
public function test_user_receives_relevant_recommendations()
{
$user = User::factory()->create();
$category = Category::factory()->create(['name' => 'Teknoloji']);
// Kullanıcının teknoloji içeriği ile etkileşime girdiğini simüle edelim
Interaction::factory()->create([
'user_id' => $user->id,
'category_id' => $category->id,
'weight' => 5
]);
$recommendations = (new RecommendationService())->getForUser($user);
$this->assertTrue($recommendations->contains('category_id', $category->id));
}
Entegrasyon testlerinde ise, veritabanındaki kayıtların güncellenmesiyle önerilerin anlık değişip değişmediğini kontrol etmelisiniz. Bu, algoritmanızın "canlı" veriyle nasıl tepki verdiğini doğrular.
Öneri Motoru Performansını İzleme ve Hata Ayıklama
Öneri motorları, özellikle büyük veri kümelerinde çalışırken "N+1" sorgu problemlerine veya yavaş çalışan karmaşık SQL sorgularına neden olabilir. Sisteminizi izlemek ve darboğazları tespit etmek için Laravel'in sunduğu araçları optimize etmeniz gerekir.
Sorgu Optimizasyonu ve Debugging
Öneri sorgularınızın ne kadar sürede çalıştığını görmek için DB::enableQueryLog() özelliğini kullanabilir veya Laravel Debugbar gibi paketlerden yararlanabilirsiniz. Özellikle withCount() veya withSum() gibi Eloquent metodlarını kullanarak veritabanı seviyesinde toplama işlemleri yapmak, PHP tarafındaki yükü ciddi oranda azaltır.
// Hatalı yaklaşım: Döngü içinde sorgu
$recommendations = Content::all()->map(function($item) {
return $item->interactions()->count(); // N+1 sorunu
});
// Doğru yaklaşım: Eager Loading ile sorgu optimizasyonu
$recommendations = Content::withCount('interactions')
->orderBy('interactions_count', 'desc')
->limit(10)
->get();
Loglama ile Hata Takibi
Algoritmanızın beklenmedik sonuçlar döndürdüğü durumları yakalamak için özel bir log kanalı oluşturun. Bu, hangi kullanıcının hangi içerik setinde hata aldığını anlamanızı sağlar:
try {
$recommendations = $this->engine->calculate($user);
} catch (\Exception $e) {
Log::channel('recommendations')->error('Öneri hatası: ' . $e->getMessage(), [
'user_id' => $user->id
]);
}
Bu hata ayıklama stratejisi, özellikle öneri motorunun "boş" sonuç döndürdüğü (fallback durumları) senaryoları yönetmenize yardımcı olur. Eğer algoritma yeterli veri bulamazsa, sistemin varsayılan olarak "En Çok Okunanlar" veya "Popüler İçerikler" gibi genel bir listeye dönmesi için bir try-catch bloğu kullanmak kullanıcı deneyimini koruyacaktır.
Sonuç
Laravel ile dinamik bir kullanıcı içerik öneri motoru kurmak, veritabanı ilişkilerini doğru yönetmek ve kullanıcı davranışlarını anlamlı verilere dönüştürmekle başlar. Bu rehberde öğrendiğiniz yöntemlerle, kullanıcılarınıza sadece içerik göstermekle kalmayacak, onların ilgisini çekecek bir deneyim sunacaksınız. Bir sonraki adım olarak, içeriklerin metin analizini (NLP) yaparak kategori bağımsız benzerlikler kurmayı deneyebilirsiniz.
Yasal Uyarı: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim (production) ortamında kullanmadan önce güvenlik açıklarını (SQL injection, XSS) gözden geçirin ve mutlaka kapsamlı testler yapın.


Yorumlar (0)
Yorum Yaz