Php İle Nesne Yönelimli Yapıda Dinamik Site İçi Arama Filtreleme Nasıl Yapılır?

Php İle Nesne Yönelimli Yapıda Dinamik Site İçi Arama Filtreleme Nasıl Yapılır?
Php İle Nesne Yönelimli Yapıda Dinamik Site İçi Arama Filtreleme Nasıl Yapılır?

PHP ile Nesne Yönelimli Yapıda Dinamik Site İçi Arama Filtreleme Nasıl Yapılır?

Modern web uygulamalarında kullanıcı deneyimini iyileştiren en kritik özelliklerden biri, verilerin hızlı ve hatasız filtrelenebilmesidir. PHP ile nesne yönelimli yapıda dinamik site içi arama filtreleme sistemi kurmak, hem kodun sürdürülebilirliğini artırır hem de veritabanı sorgularınızı daha güvenli hale getirir. Bu rehberde, 2026 standartlarına uygun, temiz kod prensiplerini benimseyen bir arama motoru mimarisini adım adım inşa edeceğiz.

Bu eğitim, orta seviye PHP bilgisine sahip geliştiriciler için hazırlanmıştır. Nesne Yönelimli Programlama (OOP) temellerini kullanarak, SQL Injection gibi güvenlik açıklarına karşı korumalı, ölçeklenebilir bir arama yapısı oluşturmayı öğreneceksiniz. Uygulama sonunda, kullanıcı girdilerini filtreleyen, veritabanından dinamik sonuçlar çeken ve sonuçları listeleyen modüler bir yapıya sahip olacaksınız.

Gereksinimler ve Ön Hazırlık

Bu projeyi başarıyla tamamlamak için sisteminizde PHP 8.2 veya üzeri bir sürümün kurulu olması gerekmektedir. Modern PHP özellikleri olan "Constructor Property Promotion" ve "Typed Properties" gibi yenilikleri kullanacağız. Veritabanı işlemleri için PDO (PHP Data Objects) kütüphanesini kullanacağız; çünkü PDO, veritabanı bağımsız çalışabilen ve güvenlik odaklı bir yapıdır.

  • PHP 8.2+ sürümü
  • MySQL veya MariaDB veritabanı sunucusu
  • PDO eklentisi aktif bir sunucu ortamı
  • Temel düzeyde SQL bilgisi

Veritabanı Yapısını ve Bağlantı Sınıfını Oluşturma

İlk adım, veritabanı bağlantısını tek bir noktadan yöneten, singleton (tekil) tasarım desenine sahip bir sınıf oluşturmaktır. Bu, uygulamanın her yerinde aynı bağlantı nesnesini kullanmanızı sağlar.


class Database {
    private static ?PDO $instance = null;

    public static function getConnection(): PDO {
        if (self::$instance === null) {
            $dsn = "mysql:host=localhost;dbname=proje_db;charset=utf8mb4";
            self::$instance = new PDO($dsn, "kullanici", "sifre", [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
            ]);
        }
        return self::$instance;
    }
}

Yukarıdaki kod, veritabanı bağlantısını güvenli bir şekilde kurar. Hata modunu exception (istisna) olarak ayarlayarak, oluşabilecek hataları try-catch blokları ile yakalamamıza olanak tanır.

Arama Filtreleme Sınıfını Tasarlama

Arama işlemlerini yönetmek için SearchManager adında bir sınıf oluşturacağız. Bu sınıf, kullanıcının gönderdiği kriterleri alacak ve dinamik SQL sorguları üretecektir. Bu yaklaşım, sorguların çalışma anında şekillenmesini sağlar.


class SearchManager {
    private PDO $db;

    public function __construct(PDO $db) {
        $this->db = $db;
    }

    public function search(string $keyword, string $category = ''): array {
        $sql = "SELECT * FROM urunler WHERE isim LIKE :keyword";
        $params = [':keyword' => '%' . $keyword . '%'];

        if (!empty($category)) {
            $sql .= " AND kategori = :kategori";
            $params[':kategori'] = $category;
        }

        $stmt = $this->db->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }
}

Bu sınıf, prepare ve execute metodlarını kullanarak SQL Injection saldırılarını tamamen engeller. Kullanıcıdan gelen veriler doğrudan sorguya eklenmez, parametre olarak bağlanır.

Dinamik Sorgu Oluşturma Mantığı

Sadece bir kelime ile değil, birden fazla filtre ile arama yapmak istiyorsanız, sorgu oluşturma mantığını bir dizi (array) üzerinden yönetmek en temiz yoldur. Aşağıdaki örnek, genişletilebilir bir arama yapısı sunar.


public function advancedSearch(array $filters): array {
    $sql = "SELECT * FROM urunler WHERE 1=1";
    $params = [];

    if (!empty($filters['q'])) {
        $sql .= " AND isim LIKE :q";
        $params[':q'] = '%' . $filters['q'] . '%';
    }
    
    if (!empty($filters['min_fiyat'])) {
        $sql .= " AND fiyat >= :min";
        $params[':min'] = $filters['min_fiyat'];
    }

    $stmt = $this->db->prepare($sql);
    $stmt->execute($params);
    return $stmt->fetchAll();
}

Burada WHERE 1=1 ifadesi, dinamik olarak eklenen AND koşullarının sorgu yapısını bozmaması için kullanılan yaygın bir tekniktir.

Arama Sonuçlarını Güvenli Şekilde Ekrana Yazdırma

Veritabanından gelen verileri kullanıcıya sunarken XSS (Cross-Site Scripting) saldırılarını önlemek için mutlaka htmlspecialchars() fonksiyonunu kullanmalısınız. Bu, veritabanındaki HTML karakterlerinin tarayıcı tarafından kod olarak çalıştırılmasını engeller.


$manager = new SearchManager(Database::getConnection());
$results = $manager->search($_GET['q'] ?? '');

foreach ($results as $row) {
    echo "
" . htmlspecialchars($row['isim'], ENT_QUOTES, 'UTF-8') . "
"; }

Bu örnek, kullanıcı girdisinin temizlenerek ekrana basılmasını sağlar. ENT_QUOTES bayrağı, hem çift hem de tek tırnakların güvenli hale getirilmesini garanti eder.

Karşılaştırma: Yöntemler ve Avantajları

Yöntem Avantaj Dezavantaj
PDO Hazırlanmış İfadeler Yüksek güvenlik, SQL injection koruması Biraz daha fazla kod satırı
Dinamik SQL String Birleştirme Esnek filtreleme Hatalı kullanımda güvenlik riski

Kritik Güvenlik Uyarısı: Kullanıcıdan gelen hiçbir veriyi (GET, POST, COOKIE) asla doğrudan SQL sorgusunun içine yazmayın. Her zaman PDO "prepared statements" (hazırlanmış ifadeler) kullanın. Üretim ortamında hata mesajlarını kullanıcıya göstermeyin; bunun yerine hata loglarını bir dosyaya kaydedin.

Sıkça Sorulan Sorular

Arama sonuçlarını nasıl sayfalayabilirim?

SQL sorgunuza LIMIT ve OFFSET ifadelerini ekleyerek, advancedSearch metodunuzu sayfalama mantığına göre güncelleyebilirsiniz.

Arama performansını nasıl artırabilirim?

Veritabanınızdaki arama yapılan sütunlara (örneğin 'isim' sütunu) INDEX (indeks) eklemek, arama hızını ciddi oranda artıracaktır.

Filtreleme çok karmaşıklaştığında ne yapmalıyım?

Eğer filtreleme kriterleriniz 5-6'yı geçiyorsa, Query Builder (Sorgu Oluşturucu) yapısına geçiş yapmayı veya popüler ORM kütüphanelerini incelemeyi düşünebilirsiniz.

Arama terimi boşsa ne yapmalıyım?

Kodunuzda mutlaka bir kontrol mekanizması kurun. Boş arama isteklerini reddedebilir veya tüm sonuçları listeleyen bir varsayılan davranış sergileyebilirsiniz.

Veri türü güvenliğini nasıl sağlarım?

PHP 8'in tip belirleme özelliklerini (Type Hinting) kullanarak metodlarınıza gelen verilerin doğru tipte olduğundan emin olun.

Arama Sisteminde Hata Ayıklama ve Loglama Stratejileri

Dinamik arama sistemlerinde en sık karşılaşılan sorunlar, yanlış yapılandırılmış SQL sorguları veya kullanıcı tarafından girilen beklenmedik veri tipleridir. Sisteminizi canlıya almadan önce, hata ayıklama süreçlerini otomatize etmek geliştirme hızınızı ciddi oranda artıracaktır. PDO hata modunu ERRMODE_EXCEPTION olarak ayarlamak, veritabanı hatalarını anında yakalamanıza olanak tanır.

Aşağıdaki örnekte, arama sınıfınızın içine entegre edebileceğiniz basit bir hata yakalama mekanizması yer almaktadır:


public function getResults(array $filters) {
    try {
        // Sorgu oluşturma mantığı burada yer alır
        $stmt = $this->db->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        // Hata loglama mekanizması
        error_log("Arama hatası: " . $e->getMessage());
        return ["error" => "Sistemde bir hata oluştu, lütfen daha sonra tekrar deneyin."];
    }
}

Bu yapıda, kullanıcıya doğrudan SQL hata mesajını göstermek yerine, sistem loglarına detaylı bilgi yazılırken kullanıcıya genel bir hata mesajı döndürülür. Bu, hem güvenlik hem de kullanıcı deneyimi açısından kritik bir yaklaşımdır.

Gelişmiş Filtreleme İçin İleri İpuçları

Arama sisteminizi daha profesyonel hale getirmek için veritabanı seviyesinde bazı optimizasyonlar ve PHP tarafında esnek yapılar kullanabilirsiniz. Özellikle "fuzzy search" (bulanık arama) veya benzerlik tabanlı aramalar için veritabanı motorunuzun sunduğu özellikleri kullanmak mantıklıdır.

Veri İndeksleme ve Performans İlişkisi

Arama yaptığınız sütunlarda (örneğin urun_adi veya kategori_id) veritabanı indeksi (INDEX) bulunması, milyonlarca satırlık veride bile milisaniyeler içinde sonuç almanızı sağlar. Eğer arama sisteminiz yavaş çalışıyorsa, sorgularınızı EXPLAIN komutu ile analiz ederek indeks kullanımını kontrol etmelisiniz.

Ayrıca, çoklu filtreleme işlemlerinde WHERE 1=1 yapısını kullanarak dinamik sorgu oluşturma sürecini şu şekilde daha temiz hale getirebilirsiniz:


public function buildQuery(array $filters) {
    $sql = "SELECT * FROM urunler WHERE 1=1";
    $params = [];

    if (!empty($filters['kategori'])) {
        $sql .= " AND kategori_id = :kategori";
        $params[':kategori'] = (int)$filters['kategori'];
    }

    if (!empty($filters['min_fiyat'])) {
        $sql .= " AND fiyat >= :min_fiyat";
        $params[':min_fiyat'] = (float)$filters['min_fiyat'];
    }

    return ['sql' => $sql, 'params' => $params];
}

Bu yöntem, filtrelerin varlığını kontrol ederek sorguyu parçalı bir şekilde inşa etmenizi sağlar. 1=1 ifadesi, SQL sözdizimini bozmadan AND operatörlerini eklemeyi kolaylaştıran standart bir yazılım desenidir.

Kullanıcı Girdilerini Doğrulama (Validation)

Sadece SQL injection koruması yeterli değildir; aynı zamanda iş mantığınızı korumak için veri doğrulama katmanı eklemelisiniz. Örneğin, bir fiyat aralığı filtresi için girilen değerin negatif olup olmadığını kontrol etmek, veritabanına gereksiz sorgu gitmesini engeller.

  • Tip Kontrolü: is_numeric() veya filter_var() fonksiyonlarını kullanın.
  • Sınır Kontrolü: Kullanıcının arama yapabileceği maksimum karakter sayısını belirleyin.
  • Beyaz Liste (Whitelist): Sıralama kriterleri (örneğin: fiyat_artan, fiyat_azalan) için sadece izin verilen değerleri kabul edin.

Sonuç

PHP ile nesne yönelimli yapıda dinamik bir arama filtreleme sistemi kurmak, uygulamanızın profesyonelliğini ve güvenliğini bir üst seviyeye taşır. Bu rehberde öğrendiğiniz PDO kullanımı, dinamik sorgu oluşturma ve veri temizleme teknikleri, geliştireceğiniz tüm projelerde temel taşlarınız olacaktır. Bir sonraki adım olarak, bu arama sistemini AJAX kullanarak sayfa yenilenmeden sonuç veren bir yapıya dönüştürmeyi deneyebilirsiniz.

Kod güvenliği sorumluluk reddi: Bu makaledeki örnekler eğitim amaçlıdır. Uygulamanızı yayına almadan önce mutlaka profesyonel güvenlik testlerinden geçirin ve veritabanı yetkilendirmelerini en düşük seviyede tutun.

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

Hobi ve teknik beceriler üzerine eğitici içerikler kurguluyorum. Okuyucuların günlük hayatta karşılaştığı sorunlara uygulanabilir çözümler sunmayı hedefliyorum.

Yorumlar (0)

Yorum Yaz