Gereksinimler ve Ön Hazırlık
Projenizi başarılı bir şekilde hayata geçirmek için bilgisayarınızda PHP 8.2 veya daha güncel bir sürümün kurulu olması gerekmektedir. Veritabanı yönetimi için MySQL veya MariaDB kullanacağız. Ayrıca, veritabanı bağlantılarını yönetmek için PDO (PHP Data Objects) eklentisinin aktif olduğundan emin olun.
- PHP 8.2+ (Tip güvenliği ve performans için önerilir)
- MySQL 8.0+ veya MariaDB
- Composer (Bağımlılık yönetimi için)
- PDO eklentisi aktif bir web sunucusu
Veritabanı Tasarımı: Favoriler Tablosu
Dinamik bir favori listesi için kullanıcılar ve içerikler arasında çoka-çok (many-to-many) bir ilişki kurmamız gerekir. Bu yapıyı desteklemek için favorites adında bir tablo oluşturacağız. Bu tablo, hangi kullanıcının hangi içeriği favorilerine eklediğini tutacaktır.
CREATE TABLE favorites (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
item_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_user_item (user_id, item_id)
) ENGINE=InnoDB;
Yukarıdaki SQL sorgusu, bir kullanıcının aynı içeriği birden fazla kez favorilere eklemesini engelleyen UNIQUE KEY kısıtlamasını içerir. Bu, veri bütünlüğü için kritik bir adımdır.
Veritabanı Bağlantısı ve PDO Yapılandırması
Nesne yönelimli yapıda veritabanı bağlantısını tek bir noktadan yönetmek, kod tekrarını önler. Bunun için bir Database sınıfı oluşturacağız. Bu sınıf, Singleton tasarım desenini kullanarak uygulama boyunca tek bir veritabanı bağlantısı sağlar.
class Database {
private static ?PDO $instance = null;
public static function getConnection(): PDO {
if (self::$instance === null) {
$dsn = "mysql:host=localhost;dbname=uygulama_db;charset=utf8mb4";
self::$instance = new PDO($dsn, 'kullanici_adi', 'sifre', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
}
return self::$instance;
}
}
Bu sınıf, veritabanı bağlantısını güvenli bir şekilde oluşturur ve hata modunu istisnaları fırlatacak (exception) şekilde ayarlar. Bu sayede hataları yakalamak çok daha kolaylaşır.
Favori Yönetimi İçin Sınıf Tasarımı
Şimdi favori işlemlerini gerçekleştirecek FavoriteManager sınıfını oluşturacağız. Bu sınıf, favori ekleme, kaldırma ve kullanıcının favorilerini listeleme gibi temel işlevleri barındıracaktır.
class FavoriteManager {
private PDO $db;
public function __construct(PDO $db) {
$this->db = $db;
}
public function addFavorite(int $userId, int $itemId): bool {
$stmt = $this->db->prepare("INSERT IGNORE INTO favorites (user_id, item_id) VALUES (?, ?)");
return $stmt->execute([$userId, $itemId]);
}
public function removeFavorite(int $userId, int $itemId): bool {
$stmt = $this->db->prepare("DELETE FROM favorites WHERE user_id = ? AND item_id = ?");
return $stmt->execute([$userId, $itemId]);
}
}
Bu kodda INSERT IGNORE kullanımı, eğer kayıt zaten varsa hata vermeden işlemi atlamasını sağlar. Ancak daha kontrollü bir yapı için try-catch blokları kullanmak her zaman daha profesyonel bir yaklaşımdır.
Dinamik Listeleme ve Güvenlik Uyarıları
Kritik Güvenlik Uyarısı: Kullanıcıdan gelen verileri (user_id, item_id) asla doğrudan sorgulara dahil etmeyin. Her zaman hazırlanan ifadeler (Prepared Statements) kullanın. Aksi takdirde SQL Injection saldırılarına açık hale gelirsiniz.
Kullanıcının favorilerini getirmek için getFavorites metodunu sınıfa ekleyelim. Bu metot, veritabanından ilgili kullanıcının tüm favori içeriklerini döndürecektir.
public function getFavorites(int $userId): array {
$stmt = $this->db->prepare("SELECT item_id FROM favorites WHERE user_id = ?");
$stmt->execute([$userId]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
Bu metot, veritabanından sadece item_id listesini döndürür. Bu, uygulamanızın diğer kısımlarında içerik detaylarını çekerken kullanabileceğiniz sade bir dizidir.
Yöntemlerin Karşılaştırmalı Özeti
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| PDO (Prepared Statements) | SQL Injection koruması sağlar | Sorgu yazımı daha uzundur |
| Session Tabanlı | Veritabanı yükünü azaltır | Kalıcı değildir, oturum kapanınca silinir |
| Veritabanı (MySQL) | Kalıcı ve güvenilirdir | Sunucuya ek yük getirir |
Sıkça Sorulan Sorular
Favori sisteminde neden veritabanı kullanmalıyım?
Veritabanı, verilerin kalıcı olmasını sağlar. Kullanıcı farklı cihazlardan giriş yaptığında favorilerine erişebilmesi için verilerin sunucu tarafında saklanması şarttır.
SQL Injection nedir ve nasıl korunurum?
SQL Injection, kötü niyetli kişilerin veritabanı sorgularını manipüle etmesidir. Hazırlanan ifadeler (Prepared Statements) kullanarak veriyi sorgudan ayırır ve bu saldırıları engellersiniz.
Performans için favori listesini nasıl önbelleğe alabilirim?
Redis veya Memcached gibi araçlar kullanarak sık erişilen favori listelerini RAM üzerinde tutabilir, veritabanı yükünü ciddi oranda düşürebilirsiniz.
Aynı anda birden fazla favori eklenirse ne olur?
Veritabanı seviyesinde tanımladığımız UNIQUE KEY kısıtlaması, veritabanının aynı veriyi mükerrer olarak kaydetmesini engeller.
OOP yapısı neden tercih edilmelidir?
OOP, kodun modüler olmasını sağlar. İleride favori sistemine "kategori bazlı filtreleme" veya "favori paylaşımı" gibi özellikler eklemek istediğinizde, mevcut yapıyı bozmadan kolayca genişletebilirsiniz.
Favori Sistemlerinde Hata Ayıklama ve Loglama Stratejileri
Dinamik bir favori sistemi geliştirirken, kullanıcıların favori ekleme veya çıkarma işlemlerinde karşılaştığı hataları izlemek, uygulamanızın kararlılığı için kritiktir. Özellikle veritabanı kilitlenmeleri veya yetkilendirme hataları, kullanıcı deneyimini doğrudan etkiler. Bu süreçte try-catch bloklarını kullanarak hataları yakalamak ve merkezi bir loglama mekanizması kurmak, sorunları hızla tespit etmenizi sağlar.
Aşağıdaki örnekte, favori ekleme işlemi sırasında oluşabilecek hataları nasıl yakalayacağınızı ve bir hata loguna nasıl yazdıracağınızı görebilirsiniz:
public function addFavorite($userId, $productId) {
try {
$stmt = $this->db->prepare("INSERT INTO favorites (user_id, product_id) VALUES (?, ?)");
return $stmt->execute([$userId, $productId]);
} catch (PDOException $e) {
// Hata loglama dosyasına yaz
error_log("Favori ekleme hatası: " . $e->getMessage(), 3, '/var/log/app_errors.log');
// Kullanıcıya dostane bir mesaj döndür
throw new Exception("İşlem sırasında bir hata oluştu, lütfen tekrar deneyin.");
}
}
Hata ayıklama sürecinde dikkat etmeniz gereken diğer noktalar şunlardır:
- Veri Tutarlılığı: Kullanıcı aynı ürünü iki kez favorilere eklemeye çalıştığında oluşabilecek
Integrity constraint violationhatasını,INSERT IGNOREveyaON DUPLICATE KEY UPDATEkullanarak yönetin. - HTTP Durum Kodları: API üzerinden çalışıyorsanız, hatalı işlemlerde
400 Bad Requestveya403 Forbiddengibi uygun HTTP kodlarını döndürün. - Girdi Doğrulama:
$userIdve$productIddeğerlerinin her zaman birer tamsayı (integer) olduğundan emin olmak içinfilter_var()fonksiyonunu kullanın.
Sistem Performansını Artırmak İçin İleri İpuçları
Favori listeleri, kullanıcı etkileşiminin yoğun olduğu alanlardır. Kullanıcı sayınız arttıkça, her sayfa yüklenişinde veritabanına yapılan SELECT sorguları sunucu yükünü artırabilir. Performansı optimize etmek için şu yöntemleri uygulayabilirsiniz:
1. İndeksleme (Indexing)
Veritabanı tablonuzda user_id ve product_id sütunlarına indeks eklemek, sorgu hızını ciddi oranda artırır. Özellikle user_id sütununa indeks eklemek, "Kullanıcının favorilerini getir" sorgusunu milisaniyeler seviyesine indirir.
-- SQL ile indeks ekleme
ALTER TABLE favorites ADD INDEX idx_user_favorites (user_id);
2. Redis ile Önbellekleme
Eğer uygulamanız çok yüksek trafik alıyorsa, favori listelerini veritabanından çekmek yerine Redis gibi bir anahtar-değer deposunda tutabilirsiniz. Kullanıcı bir favori eklediğinde, veritabanına yazmanın yanı sıra Redis'teki ilgili listeyi de güncelleyin.
// Redis kullanımı örneği
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// Kullanıcının favori ID'lerini Redis set'inde tutma
$redis->sAdd("user_favs:" . $userId, $productId);
3. Lazy Loading (Tembel Yükleme)
Kullanıcının profil sayfasında favori listesini göstermek yerine, "Favorilerimi Gör" butonuna tıklandığında AJAX ile veriyi çekmek, ana sayfa yüklenme süresini optimize eder. Bu sayede gereksiz veritabanı sorgularının önüne geçmiş olursunuz.
Profesyonel İpucu: Veritabanı sorgularınızdaSELECT *yerine sadece ihtiyacınız olan sütunları (örneğinproduct_id) seçmek, bellek kullanımını azaltır ve ağ trafiğini optimize eder.
Sonuç
PHP ile nesne yönelimli bir favori sistemi oluşturmak, uygulamanızın temel yapı taşlarından biridir. Bu rehberde, veritabanı tasarımından başlayarak güvenli sorgu yazımına ve OOP prensiplerine kadar kritik adımları inceledik. Bir sonraki adım olarak, bu favori listesini AJAX kullanarak sayfa yenilenmeden güncelleyen bir JavaScript arayüzü ekleyebilir ve kullanıcı deneyimini bir üst seviyeye taşıyabilirsiniz.
Yasal Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce, veritabanı bağlantı bilgilerini güvenli bir şekilde (örneğin .env dosyaları ile) sakladığınızdan ve tüm girdileri doğruladığınızdan emin olun.

Yorumlar (0)
Yorum Yaz