PHP ile Veritabanı Destekli Dinamik Bir Sınav Modülü Nasıl Yapılır?
PHP ile veritabanı destekli dinamik bir sınav modülü geliştirmek, hem web programlama temellerini pekiştirmek hem de ölçeklenebilir eğitim yazılımları oluşturmak için mükemmel bir projedir. Bu rehberde, 2026 standartlarına uygun olarak, veritabanı tasarımı, soru yönetimi ve kullanıcı etkileşimli bir sınav akışının nasıl oluşturulacağını adım adım inceleyeceğiz.
Bu makale, PHP ve MySQL kullanarak kendi sınav platformunu kurmak isteyen orta seviye geliştiriciler için hazırlanmıştır. Proje boyunca PDO (PHP Data Objects) kullanarak güvenli veritabanı işlemleri yapmayı, SQL injection açıklarını engellemeyi ve dinamik içerik sunumunu öğreneceksiniz.
Gereksinimler ve Ön Hazırlık
Başarılı bir uygulama geliştirmek için sisteminizde güncel bir yazılım yığını bulunmalıdır. PHP 8.3 veya üzeri bir sürüm, modern sözdizimi ve performans iyileştirmeleri nedeniyle önerilmektedir. Veritabanı yönetimi için MariaDB veya MySQL kullanacağız.
- PHP 8.3+: Modern, tip güvenli (type-safe) kod yazımı için.
- MySQL/MariaDB: İlişkisel veritabanı yönetimi için.
- PDO Sürücüsü: Veritabanı işlemlerini güvenli hale getirmek için.
- Bir Kod Editörü: VS Code veya benzeri bir IDE.
Veritabanı Tasarımı ve SQL Tabloları
Dinamik bir sınav modülünün kalbi, soruların ve cevapların doğru modellenmesidir. İki ana tabloya ihtiyacımız var: sorular ve secenekler. Bu yapı, tek bir sorunun birden fazla seçeneğe sahip olmasını sağlar.
CREATE TABLE sorular (
id INT AUTO_INCREMENT PRIMARY KEY,
soru_metni TEXT NOT NULL,
zorluk_derecesi INT DEFAULT 1
);
CREATE TABLE secenekler (
id INT AUTO_INCREMENT PRIMARY KEY,
soru_id INT,
secenek_metni VARCHAR(255) NOT NULL,
dogru_mu BOOLEAN DEFAULT FALSE,
FOREIGN KEY (soru_id) REFERENCES sorular(id) ON DELETE CASCADE
);
Yukarıdaki SQL komutları, veritabanı bütünlüğünü korumak için FOREIGN KEY (yabancı anahtar) kullanarak sorular ve seçenekler arasında ilişki kurar. ON DELETE CASCADE özelliği, bir soru silindiğinde ona bağlı tüm seçeneklerin otomatik olarak temizlenmesini sağlar.
Veritabanı Bağlantısı ve PDO Kullanımı
Güvenlik için veritabanı bağlantısında mutlaka PDO kullanmalısınız. PDO, SQL injection saldırılarına karşı hazırlıklı ifadeler (prepared statements) sunar. Aşağıdaki kod, veritabanına güvenli bir bağlantı kurmanızı sağlar.
Bu bağlantı dosyası, uygulamanın her yerinde kullanacağımız $pdo nesnesini oluşturur. PDO::ATTR_ERRMODE ayarı, hataların yakalanabilir olmasını sağlar.
Dinamik Soru Listeleme ve Form Oluşturma
Veritabanındaki soruları çekip kullanıcıya bir HTML formu olarak sunmak, modülün en kritik adımıdır. Her soruyu bir döngü içerisinde listeleyerek kullanıcıdan cevap alacağız.
Sınav Sonuçlarını Hesaplama ve Veritabanına Kaydetme
Kullanıcı formu gönderdiğinde, gelen verileri işlemek ve doğru cevaplarla karşılaştırarak puanı hesaplamak gerekir. Bu süreçte, formdan gelen soru_id ve cevap_id değerlerini veritabanındaki doğru cevaplarla kıyaslayan bir mantık kurmalıyız.
Aşağıdaki kod bloğu, form gönderildiğinde çalışacak olan sonuç hesaplama mantığını göstermektedir:
// cevap_kontrol.php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$dogru_sayisi = 0;
foreach ($_POST['cevaplar'] as $soru_id => $secilen_cevap_id) {
$stmt = $pdo->prepare("SELECT dogru_cevap_id FROM sorular WHERE id = ?");
$stmt->execute([$soru_id]);
$soru = $stmt->fetch();
if ($soru && $soru['dogru_cevap_id'] == $secilen_cevap_id) {
$dogru_sayisi++;
}
}
echo "Toplam Doğru Sayınız: " . $dogru_sayisi;
// Sonucu veritabanına kaydetme
$kaydet = $pdo->prepare("INSERT INTO sinav_sonuclari (kullanici_id, puan) VALUES (?, ?)");
$kaydet->execute([$_SESSION['user_id'], $dogru_sayisi]);
}
Performans Optimizasyonu ve İleri İpuçları
Sınav modülünüz büyüdükçe ve soru sayısı arttıkça, veritabanı sorgularının verimliliği önem kazanır. Özellikle her soru için ayrı bir sorgu çalıştırmak yerine, tüm soruları tek bir JOIN işlemi ile çekmek sunucu yükünü ciddi oranda azaltacaktır.
Veritabanı Sorgularını Optimize Etme
Soru ve seçenekleri tek seferde çekmek için aşağıdaki gibi bir sorgu yapısı kullanabilirsiniz:
$sql = "SELECT s.id AS soru_id, s.soru_metni, c.id AS secenek_id, c.secenek_metni
FROM sorular s
LEFT JOIN secenekler c ON s.id = c.soru_id
ORDER BY s.id ASC";
$stmt = $pdo->query($sql);
$sinav_verileri = $stmt->fetchAll(PDO::FETCH_GROUP);
İleri Düzey İpuçları:
- Önbellekleme (Caching): Çok fazla katılımcısı olan bir sınavda, soruları her seferinde veritabanından çekmek yerine Redis veya dosya tabanlı önbellekleme sistemlerini kullanın.
- Zaman Sınırı: Kullanıcıların sınavı tamamlaması için JavaScript tabanlı bir geri sayım sayacı ekleyin ve süre bittiğinde formu otomatik olarak gönderen bir
submit() fonksiyonu tanımlayın.
- Güvenlik Katmanı: Kullanıcının sınav sayfasını yenilediğinde puanının tekrar hesaplanmaması için
$_SESSION üzerinden bir "sınav_tamamlandı" kontrolü eklemeyi unutmayın.
Bu yapı, modülünüzün hem ölçeklenebilir olmasını sağlar hem de kullanıcı deneyimini iyileştirerek sistemin daha hızlı yanıt vermesine olanak tanır.


Yorumlar (0)
Yorum Yaz