PHP ile Nesne Yönelimli Yapıda Dinamik Site İçi Arama Önerisi Nasıl Yapılır?
Modern web uygulamalarında kullanıcı deneyimini iyileştiren en kritik özelliklerden biri, arama çubuğuna yazılan her karakterle birlikte anlık sonuçlar döndüren "canlı arama" veya "arama önerisi" sistemleridir. PHP ile nesne yönelimli (OOP) yapıda dinamik site içi arama önerisi oluşturmak, uygulamanızın performansını ve kullanıcı etkileşimini doğrudan artırır. Bu rehberde, 2026 standartlarına uygun, güvenli ve ölçeklenebilir bir arama öneri mekanizmasını adım adım inşa edeceğiz.
Bu eğitim, PHP 8.x ve üzeri sürümlerini kullanan, veritabanı işlemlerinde PDO (PHP Data Objects) yapısına hakim olan geliştiriciler için hazırlanmıştır. Arama önerisi sistemini kurarken sunucu tarafında PHP, istemci tarafında ise modern JavaScript (Fetch API) kullanarak tam bir etkileşimli yapı kurmayı hedefliyoruz.
Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. Dinamik bir arama sistemi için ihtiyaç duyacağınız temel araçlar şunlardır:
- PHP 8.2 veya üzeri: Tip güvenliği ve performans iyileştirmeleri için gereklidir.
- MySQL 8.0 veya MariaDB: FULLTEXT index desteği olan bir veritabanı motoru.
- PDO Sürücüsü: Güvenli veritabanı sorguları için standarttır.
- Modern Tarayıcı: Fetch API ve DOM manipülasyonlarını test etmek için.
Veritabanınızda arama yapılacak tablonun (örneğin urunler tablosu) ad sütununa FULLTEXT indeksi eklemeniz, sorgu hızını ciddi oranda artıracaktır. Aşağıdaki SQL komutu ile tablonuzu hazırlayabilirsiniz:
ALTER TABLE urunler ADD FULLTEXT(ad);
Adım 1: Veritabanı Bağlantısı ve Nesne Yönelimli Yapı
OOP prensiplerine uygun bir veritabanı sınıfı oluşturmak, uygulamanın geri kalanında kod tekrarını önler. Singleton veya Dependency Injection yaklaşımlarını tercih edebilirsiniz. Biz burada basit ve etkili bir bağlantı sınıfı kullanacağız.
class Database {
private PDO $pdo;
public function __construct() {
$dsn = "mysql:host=localhost;dbname=proje_db;charset=utf8mb4";
$this->pdo = new PDO($dsn, 'kullanici', 'sifre', [
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ı detaylarını izole eder ve güvenli bir PDO nesnesi sağlar. ATTR_ERRMODE ayarı, hataların yakalanabilir olmasını sağlarken, charset=utf8mb4 Türkçe karakter desteği için kritiktir.
Adım 2: Arama İşleme Sınıfını Oluşturma
Arama önerilerini getirecek olan mantığı ayrı bir sınıf içerisinde toplamak, kodun test edilebilirliğini artırır. Bu sınıf, kullanıcıdan gelen girdiyi temizlemeli ve SQL Injection saldırılarına karşı hazırlıklı olmalıdır.
class SearchService {
private PDO $db;
public function __construct(PDO $db) {
$this->db = $db;
}
public function getSuggestions(string $query): array {
$stmt = $this->db->prepare("SELECT id, ad FROM urunler WHERE ad LIKE :query LIMIT 5");
$stmt->execute(['query' => '%' . $query . '%']);
return $stmt->fetchAll();
}
}
Burada LIKE operatörü ile basit bir eşleşme yapıyoruz. Ancak daha büyük verisetlerinde MATCH() AGAINST() fonksiyonunu kullanmanız önerilir. Girdi temizliği için prepare ve execute metodları sayesinde veritabanı güvenliğini sağlamış oluyoruz.
Adım 3: JSON Çıktısı Veren API Uç Noktası
İstemci tarafındaki JavaScript kodunun veriyi alabilmesi için PHP tarafında bir JSON yanıtı üretmemiz gerekir. Bu dosya (örneğin api/arama.php) sadece veriyi döndürmeli ve uygun başlıkları (header) ayarlamalıdır.
header('Content-Type: application/json');
require_once '../Database.php';
require_once '../SearchService.php';
$db = (new Database())->getConnection();
$service = new SearchService($db);
$q = $_GET['q'] ?? '';
if (strlen($q) > 2) {
echo json_encode($service->getSuggestions($q));
} else {
echo json_encode([]);
}
Bu kod bloğu, gelen q parametresini alır, en az 3 karakter uzunluğunda olup olmadığını kontrol eder ve sonuçları JSON formatında istemciye gönderir. Bu yapı, uygulamanın dinamikleşmesini sağlayan köprüdür.
Adım 4: JavaScript ile Dinamik Arama Önerisi
Kullanıcı arama çubuğuna her tuşa bastığında (keyup event), Fetch API ile PHP API'mize istek atmalıyız. Bu işlem, kullanıcıya anlık öneriler sunmamızı sağlar.
const searchInput = document.querySelector('#arama-kutusu');
const resultsBox = document.querySelector('#sonuc-kutusu');
searchInput.addEventListener('keyup', async () => {
const query = searchInput.value;
if (query.length < 3) { resultsBox.innerHTML = ''; return; }
const response = await fetch(`api/arama.php?q=${encodeURIComponent(query)}`);
const data = await response.json();
resultsBox.innerHTML = data.map(item => `${item.ad}`).join('');
});
encodeURIComponent kullanımı, kullanıcı girdisindeki özel karakterlerin URL yapısını bozmasını engeller. Bu adım, arayüzün akıcılığını doğrudan etkileyen en önemli kısımdır.
Adım 5: Karşılaştırmalı Yöntemler ve Performans
Arama önerisi sistemlerinde farklı yöntemler kullanılabilir. İhtiyacınıza göre en uygun yöntemi seçmek için aşağıdaki tabloyu inceleyebilirsiniz.
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| LIKE %sorgu% | Basit, kurulum gerektirmez | Büyük veride yavaştır |
| FULLTEXT Index | Çok hızlıdır, doğal dil işler | Sadece belirli sütunlarda çalışır |
| Elasticsearch | Profesyonel ölçekleme | Karmaşık yapı, ek sunucu maliyeti |
Güvenlik ve Performans Uyarıları
Dikkat: Kullanıcıdan gelen verileri asla doğrudan SQL sorgusuna dahil etmeyin. Her zaman PDO
preparemetodunu kullanın. Ayrıca, arama önerisi sistemlerinde "Debounce" tekniğini kullanarak, kullanıcı her tuşa bastığında sunucuya istek gitmesini engelleyip, yazmayı bitirdiğinde (örneğin 300ms sonra) istek gönderilmesini sağlayın. Bu, sunucu yükünü %80 oranında azaltacaktır.
Sıkça Sorulan Sorular
Arama önerisinde neden 3 karakter sınırı koymalıyım?
Kullanıcı henüz anlamlı bir kelime yazmadan veritabanına sorgu göndermek, gereksiz sunucu yükü yaratır ve veritabanı performansını düşürür. 3 karakter, genellikle anlamlı bir arama için ideal alt sınırdır.
SQL Injection saldırılarına karşı tam koruma sağladım mı?
PDO ve prepared statements kullanımı, SQL Injection'a karşı en güçlü savunmadır. Ancak, veritabanı kullanıcısının yetkilerini sadece gerekli tablolara (SELECT yetkisi gibi) kısıtlamak, "En Az Ayrıcalık" prensibi gereği ek bir güvenlik katmanıdır.
Arama sonuçlarını önbelleğe alabilir miyim?
Evet, Redis veya Memcached kullanarak sık aranan kelimelerin sonuçlarını önbelleğe alabilirsiniz. Bu, veritabanı üzerindeki yükü neredeyse sıfıra indirir.
Mobil cihazlarda bu yapı nasıl davranır?
Fetch API ve modern JavaScript, tüm mobil tarayıcılarda desteklenir. Sadece arayüzün (CSS) mobil uyumlu (responsive) olduğundan emin olmanız yeterlidir.
Neden LIKE yerine FULLTEXT öneriyorsunuz?
LIKE '%kelime%' sorgusu, veritabanındaki tüm satırları taramak zorundadır (Full Table Scan). FULLTEXT ise bir indeks yapısı kullandığı için aranan kelimeyi doğrudan bulur, bu da binlerce satırlık tabloda bile milisaniyeler içinde sonuç almanızı sağlar.
Arama Deneyimini İyileştirmek İçin İleri İpuçları
Temel arama yapısını kurduktan sonra, kullanıcı deneyimini (UX) daha üst seviyeye taşımak için bazı stratejik geliştirmeler yapabilirsiniz. Arama kutusu etkileşimlerini optimize etmek, kullanıcıların aradıkları içeriğe çok daha hızlı ulaşmasını sağlar.
Debounce (Gecikmeli Arama) Tekniği
Kullanıcı her tuşa bastığında sunucuya istek göndermek, hem veritabanını yorar hem de gereksiz trafik oluşturur. "Debounce" tekniği ile kullanıcının yazmayı bırakmasını bekleyerek istek sayısını minimize edebilirsiniz.
let timeout = null;
const searchInput = document.querySelector('#search-box');
searchInput.addEventListener('keyup', function() {
clearTimeout(timeout);
timeout = setTimeout(() => {
performSearch(this.value);
}, 300); // Kullanıcı yazmayı bıraktıktan 300ms sonra tetiklenir
});
Arama Sonuçlarını Öne Çıkarma (Highlighting)
Kullanıcının aradığı kelimeyi sonuçlar içerisinde kalın (bold) olarak göstermek, görsel algıyı güçlendirir. Bu işlemi JavaScript tarafında basit bir replace fonksiyonu ile yapabilirsiniz.
function highlightText(text, query) {
const regex = new RegExp(`(${query})`, 'gi');
return text.replace(regex, '$1');
}
Arama Performansını İzleme ve Hata Ayıklama
Sistemin sağlıklı çalıştığından emin olmak için geliştirme aşamasında bazı metrikleri takip etmeniz önemlidir. Özellikle yavaş sorguları tespit etmek, veritabanı optimizasyonu için kritiktir.
Yavaş Sorgu Günlüğü (Slow Query Log)
MySQL üzerinde 1 saniyeden uzun süren sorguları tespit etmek için my.cnf veya my.ini dosyanızda şu ayarları aktif edebilirsiniz:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 1
Hata Ayıklama (Debugging) Stratejisi
API yanıtlarında beklenmedik sonuçlar aldığınızda, PHP tarafında hata loglarını aktif ederek süreci takip edin. Üretim (production) ortamında hata mesajlarını kullanıcıya göstermemeli, bunun yerine bir log dosyasına yazmalısınız.
try {
// Arama mantığı
} catch (Exception $e) {
error_log("Arama Hatası: " . $e->getMessage());
echo json_encode(['error' => 'Sistemde bir hata oluştu.']);
exit;
}
Performans Karşılaştırma Tablosu
| Yöntem | Hız | Kaynak Tüketimi | Ölçeklenebilirlik |
|---|---|---|---|
| LIKE Sorgusu | Düşük | Yüksek | Zayıf |
| FULLTEXT İndeksi | Yüksek | Düşük | İyi |
| Elasticsearch/Algolia | Çok Yüksek | Çok Düşük | Mükemmel |
Küçük ve orta ölçekli projeler için FULLTEXT indeksleme yeterli olacaktır. Ancak milyonlarca satırlık verilerle çalışıyorsanız, PHP tabanlı arama yerine Elasticsearch gibi özel arama motorlarına geçiş yapmayı planlamalısınız.
Sonuç
PHP ile nesne yönelimli bir yapıda dinamik site içi arama önerisi oluşturmak, uygulamanızın profesyonellik seviyesini bir üst noktaya taşır. Bu rehberde öğrendiğiniz PDO kullanımı, JSON tabanlı API tasarımı ve JavaScript etkileşimleri, modern web geliştirmenin temel taşlarıdır. Bir sonraki adım olarak, arama sonuçlarınıza görsel (resim) eklemeyi veya arama terimlerini bir "log" tablosuna kaydederek en çok aranan kelimeleri analiz etmeyi deneyebilirsiniz.

Yorumlar (0)
Yorum Yaz