Php İle Nesne Yönelimli Yapıda Dinamik Bir Favori Listesi Nasıl Yapılır?

Php İle Nesne Yönelimli Yapıda Dinamik Bir Favori Listesi Nasıl Yapılır?
Php İle Nesne Yönelimli Yapıda Dinamik Bir Favori Listesi Nasıl Yapılır?

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 violation hatasını, INSERT IGNORE veya ON DUPLICATE KEY UPDATE kullanarak yönetin.
  • HTTP Durum Kodları: API üzerinden çalışıyorsanız, hatalı işlemlerde 400 Bad Request veya 403 Forbidden gibi uygun HTTP kodlarını döndürün.
  • Girdi Doğrulama: $userId ve $productId değerlerinin her zaman birer tamsayı (integer) olduğundan emin olmak için filter_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ızda SELECT * yerine sadece ihtiyacınız olan sütunları (örneğin product_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.

Bu yazıya tepkinizi paylaşın:
Zeynep Çelik

Modern yaşam ipuçları ve kişisel gelişim üzerine içerik tasarlıyorum. Günlük hayatı kolaylaştıran hızlı ve etkili çözüm odaklı yazılar yazmayı seviyorum.

Yorumlar (0)

Yorum Yaz