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

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

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce sisteminizde PHP 8.1 veya üzeri bir sürümün yüklü olduğundan emin olmalısınız. Veritabanı bağlantısı için PDO sürücüsünün aktif olması gerekmektedir. Ayrıca, veritabanı işlemlerini yürütecek bir MySQL veya MariaDB sunucusuna erişiminiz olmalıdır.

  • PHP 8.1+: Modern özellikler (readonly sınıflar, constructor promotion) için gereklidir.
  • PDO Sürücüsü: Güvenli sorgular için standarttır.
  • Veritabanı Tablosu: Arama terimlerini saklamak için uygun bir tablo yapısı.

Aşağıdaki SQL komutu ile arama kayıtlarını tutacağımız tabloyu oluşturabilirsiniz. Bu tablo, aranan kelimeyi, arama zamanını ve kullanıcının IP adresini kaydederek analitik veri toplamanıza olanak tanır.

CREATE TABLE search_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    search_term VARCHAR(255) NOT NULL,
    search_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    ip_address VARCHAR(45) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Veritabanı Bağlantısını Nesne Yönelimli Yapıda Kurmak

Veritabanı bağlantısını her sayfada tekrar yazmak yerine, bir Database sınıfı oluşturmak en iyi pratiklerden biridir. Bu yapı, kod tekrarını önler ve merkezi bir bağlantı yönetimi sağlar.

class Database {
    private string $host = 'localhost';
    private string $db   = 'proje_adi';
    private string $user = 'root';
    private string $pass = '';
    private PDO $pdo;

    public function __construct() {
        $dsn = "mysql:host=$this->host;dbname=$this->db;charset=utf8mb4";
        $this->pdo = new PDO($dsn, $this->user, $this->pass, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]);
    }

    public function getConnection(): PDO {
        return $this->pdo;
    }
}

Bu sınıf, veritabanı bağlantısını tek bir noktadan yönetmemizi sağlar. PDO::ATTR_ERRMODE ayarı ile hataların yakalanmasını kolaylaştırıyoruz.

Arama Kaydı İşlemleri İçin Sınıf Oluşturma

Arama kayıtlarını veritabanına eklemek için özel bir SearchLogger sınıfı tasarlamalıyız. Bu sınıf, sadece kayıt ekleme görevini üstlenerek "Single Responsibility" (Tek Sorumluluk) prensibine uygun hareket eder.

class SearchLogger {
    private PDO $db;

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

    public function logSearch(string $term): void {
        $stmt = $this->db->prepare("INSERT INTO search_logs (search_term, ip_address) VALUES (?, ?)");
        $stmt->execute([htmlspecialchars($term), $_SERVER['REMOTE_ADDR']]);
    }
}

Burada htmlspecialchars fonksiyonu, XSS (Cross-Site Scripting) saldırılarını engellemek için kritik bir önlemdir. Kullanıcıdan gelen veriye asla güvenmemeli ve her zaman filtrelemelisiniz.

Kritik Güvenlik Uyarısı: Kullanıcıdan alınan verileri veritabanına kaydederken mutlaka "Prepared Statements" kullanın. Asla doğrudan değişkenleri sorgu içine gömmeyin; bu, SQL Injection saldırılarına kapı açar.

Dinamik Arama ve Kayıt Süreci Nasıl Yapılır?

Şimdi, arama formundan gelen veriyi alıp hem arama sonucunu getiren hem de bu aramayı kaydeden ana mantığı kuralım. Bu süreç, kullanıcı bir arama yaptığında eş zamanlı olarak çalışır.

// Kullanıcı arama yaptığında
if (isset($_GET['q']) && !empty($_GET['q'])) {
    $searchTerm = $_GET['q'];
    
    $db = (new Database())->getConnection();
    $logger = new SearchLogger($db);
    
    // Aramayı kaydet
    $logger->logSearch($searchTerm);
    
    // Arama sonuçlarını getir (Örnek)
    $stmt = $db->prepare("SELECT * FROM urunler WHERE isim LIKE ?");
    $stmt->execute(['%' . $searchTerm . '%']);
    $results = $stmt->fetchAll();
}

Bu kod bloğu, kullanıcının girdiği terimi önce veritabanına yazar, ardından ürünler tablosunda eşleşen kayıtları arar. Bu sayede hem kullanıcıya sonuç döner hem de sisteminiz arama trendlerini öğrenir.

Yöntem Karşılaştırması

Yöntem Avantajı Dezavantajı
PDO Prepared Statements SQL Injection koruması, yüksek performans Ekstra kod satırı gerektirir
Doğrudan Sorgu (Riskli) Hızlı yazılır Güvenlik açığı, veri sızıntısı riski

Sıkça Sorulan Sorular

Arama kayıtlarını tutmak veritabanını yavaşlatır mı?

Küçük ve orta ölçekli sitelerde bu işlem bir performans kaybına neden olmaz. Ancak çok yüksek trafikli sitelerde, arama kayıtlarını asenkron bir kuyruk sistemine (Redis veya RabbitMQ gibi) almanız önerilir.

SQL Injection nedir ve neden korunmalıyım?

SQL Injection, kötü niyetli kişilerin veritabanı sorgularını manipüle ederek verilerinizi çalması veya silmesidir. PDO kullanmak bu riski %99 oranında ortadan kaldırır.

Arama sonuçlarını nasıl daha alakalı hale getirebilirim?

Sadece LIKE operatörü yerine, MySQL'in FULLTEXT INDEX özelliğini kullanmanız arama kalitesini ciddi oranda artıracaktır.

IP adreslerini kaydetmek yasal mı?

Kullanıcı IP adresleri kişisel veri kapsamına girebilir. KVKK uyumu için gizlilik politikanızda bu verileri neden topladığınızı belirtmeniz ve anonimleştirme yöntemlerini değerlendirmeniz gerekebilir.

Aynı terim tekrar tekrar aranırsa ne yapmalıyım?

Arama günlüğünüzün şişmemesi için, logSearch fonksiyonu içine "son 1 saatte aynı IP'den aynı terim arandıysa tekrar kaydetme" gibi bir kontrol mekanizması ekleyebilirsiniz.

Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce mutlaka kapsamlı güvenlik testlerinden geçirin ve sunucu yapılandırmanızı güncel tutun.

Arama Kayıtları İçin Performans Optimizasyonu ve İndeksleme

Veritabanınız büyüdükçe, arama kayıtlarının tutulduğu tablodaki sorgu süreleri artabilir. Özellikle binlerce veya milyonlarca kayıt içeren bir tabloda SELECT işlemleri yavaşlayacaktır. Bu durumu engellemek için veritabanı seviyesinde indeksleme stratejileri uygulamak kritiktir.

Arama terimi (search_term) ve arama zamanı (created_at) sütunlarına indeks ekleyerek sorgu performansını ciddi oranda artırabilirsiniz. Aşağıdaki SQL komutu, arama terimleri üzerinden yapılan filtrelemeleri hızlandıracaktır:

CREATE INDEX idx_search_term ON search_logs(search_term);
CREATE INDEX idx_created_at ON search_logs(created_at);

Ayrıca, çok büyük verilerle çalışıyorsanız "Partitioning" (bölümleme) yöntemini kullanabilirsiniz. Örneğin, her ay için ayrı bir tablo oluşturmak veya verileri aylık periyotlarla arşivlemek, ana tablonun her zaman hızlı kalmasını sağlar.

Hata Ayıklama ve Log Yönetimi

Arama kayıt sisteminizde oluşabilecek hataları (veritabanı bağlantı kopması, yazma yetkisi sorunları vb.) kullanıcıya yansıtmadan arka planda yakalamak, sistemin sürekliliği için önemlidir. PDO'nun try-catch bloklarını kullanarak hataları bir log dosyasına yazdırabilirsiniz.

Aşağıdaki örnek, veritabanı yazma işlemi başarısız olduğunda uygulamanın çökmesini engeller ve hatayı sunucu tarafında bir dosyaya kaydeder:

public function logSearch($term, $ip) {
    try {
        $stmt = $this->db->prepare("INSERT INTO search_logs (search_term, ip_address) VALUES (?, ?)");
        $stmt->execute([$term, $ip]);
    } catch (PDOException $e) {
        // Hata detayını gizli bir log dosyasına yaz
        error_log("Arama kaydı hatası: " . $e->getMessage(), 3, '/var/log/app_errors.log');
        // Kullanıcıya hata gösterme, sadece işlemi sessizce atla
        return false;
    }
}

İleri İpuçları: Arama Terimlerini Normalleştirme

Kullanıcılar aynı terimi farklı şekillerde arayabilir (örneğin: "php dersleri", "PHP DERSLERİ", "php dersleri "). Bu durum, analitik verilerinizin parçalanmasına neden olur. Kayıt yapmadan önce veriyi temizlemek ve standart hale getirmek, raporlarınızın doğruluğunu artırır.

Veriyi kaydetmeden önce uygulayabileceğiniz basit bir normalleştirme örneği:

public function normalizeTerm($term) {
    // 1. Boşlukları kırp
    $term = trim($term);
    // 2. Küçük harfe çevir
    $term = mb_strtolower($term, 'UTF-8');
    // 3. HTML etiketlerini temizle
    $term = strip_tags($term);
    return $term;
}

// Kullanımı:
$cleanTerm = $searchEngine->normalizeTerm($_GET['q']);
$searchEngine->logSearch($cleanTerm, $_SERVER['REMOTE_ADDR']);

Bu yöntemle, "PHP" ve "php " gibi aramalar veritabanında tek bir başlık altında toplanarak daha anlamlı istatistikler elde etmenizi sağlar.

Sonuç

Php ile nesne yönelimli yapıda dinamik site içi arama kaydı oluşturmak, projenize hem güvenlik hem de analitik derinlik katar. Bu rehberde öğrendiğiniz PDO kullanımı, sınıf tabanlı mimari ve XSS/SQL Injection koruması, profesyonel bir yazılımcının temel yetkinlikleridir. Bir sonraki adım olarak, kaydedilen bu verileri bir yönetici panelinde görselleştiren bir grafik kütüphanesi (örneğin Chart.js) entegre edebilirsiniz.

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

Kendin yap (DIY) projeleri ve ev içi bakım rehberleri üzerine içerik geliştiriyorum. Detaylı ve anlaşılır anlatım diliyle karmaşık işleri keyifli hale getiriyorum.

Yorumlar (0)

Yorum Yaz