Gereksinimler ve Ön Hazırlık
Projenizi yerel bilgisayarınızda veya sunucunuzda çalıştırmak için aşağıdaki araçların yüklü ve yapılandırılmış olması gerekir. 2026 yılı standartlarına uygun olarak PHP 8.2 veya üzeri sürümleri kullanmanızı öneriyoruz.
- PHP 8.2+: Modern sözdizimi ve performans iyileştirmeleri için gereklidir.
- MySQL veya MariaDB: Verilerin kalıcı olarak saklanması için kullanılacaktır.
- PDO (PHP Data Objects): Veritabanı işlemleri için güvenli ve veritabanından bağımsız bir arayüz sağlar.
- Web Sunucusu: Apache veya Nginx üzerinde çalışan yerel bir geliştirme ortamı (XAMPP, Laragon veya Docker).
Veritabanı Tasarımı ve Tablo Yapısı
Dinamik bir anket sistemi için en az iki ana tabloya ihtiyacımız vardır: anket sorularını tutan tablo ve kullanıcıların verdiği yanıtları kaydeden tablo. Bu yapı, ileride yeni sorular eklemenizi kolaylaştırır.
-- Anket soruları tablosu
CREATE TABLE anket_sorulari (
id INT AUTO_INCREMENT PRIMARY KEY,
soru_metni VARCHAR(255) NOT NULL,
olusturulma_tarihi TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Yanıtlar tablosu
CREATE TABLE anket_yanitlari (
id INT AUTO_INCREMENT PRIMARY KEY,
soru_id INT NOT NULL,
secenek VARCHAR(100) NOT NULL,
FOREIGN KEY (soru_id) REFERENCES anket_sorulari(id) ON DELETE CASCADE
);
Yukarıdaki SQL kodları, ilişkisel veritabanı modelini kurar. FOREIGN KEY kullanımı, bir soru silindiğinde ona bağlı tüm yanıtların da otomatik olarak temizlenmesini sağlar (CASCADE özelliği).
Veritabanı Bağlantısını Güvenli Hale Getirme
Veritabanı bağlantısı için PDO sınıfını kullanmak, kodunuzun güvenliğini artırır. Aşağıdaki örnekte, veritabanı bağlantısını bir sınıf veya basit bir dosya olarak nasıl tanımlayacağımızı görebilirsiniz.
Bu bağlantı bloğu, hata modunu istisnalar (exceptions) fırlatacak şekilde ayarlar. Bu, üretim ortamında hataları gizlemek ve loglamak için kritik bir öneme sahiptir.
Anket Sorularını ve Seçeneklerini Listeleme
Kullanıcıya anketi göstermek için veritabanından verileri çekmemiz gerekir. Dinamik yapı olduğu için sabit HTML yerine PHP döngülerini kullanacağız.
Burada htmlspecialchars fonksiyonunu kullanarak XSS (Cross-Site Scripting) saldırılarını engelliyoruz. Kullanıcıdan gelen veya veritabanından çekilen her veriyi mutlaka filtrelemelisiniz.
Kullanıcı Yanıtlarını İşleme ve Kaydetme
Kullanıcı formu gönderdiğinde, veriyi güvenli bir şekilde veritabanına eklememiz gerekir. Hazırlanmış ifadeler (Prepared Statements) kullanarak SQL Injection saldırılarını tamamen etkisiz hale getiriyoruz.
Formun gönderildiği sayfada, $_POST verilerini doğrudan sorguya sokmak yerine ? yer tutucularını kullanmak, veritabanı güvenliğinin altın kuralıdır.
Veri Gösterim Yöntemlerinin Karşılaştırılması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| PDO (Prepared Statements) | SQL Injection koruması, yüksek güvenlik | Küçük projeler için kurulum gerektirir |
| mysqli_query (Eski) | Basit sözdizimi | Güvenlik açığına çok açık, önerilmez |
Kritik Güvenlik Uyarısı: Üretim ortamında (production) hiçbir zaman
display_errorsayarını açık bırakmayın. Veritabanı şifrelerinizi kod içerisinde düz metin olarak tutmak yerine, ortam değişkenlerini (.env dosyaları) kullanın. Kod güvenliği konusunda sorumluluk tamamen geliştiriciye aittir; her kullanıcı girdisini mutlaka doğrulayın ve temizleyin.
Sıkça Sorulan Sorular
Anket sisteminde mükerrer oy kullanımını nasıl engellerim?
Kullanıcının IP adresini veya giriş yapmışsa kullanıcı ID'sini bir çerez (cookie) veya veritabanı tablosunda tutarak, aynı kişinin tekrar oy vermesini engelleyebilirsiniz.
Veritabanı bağlantısı neden PDO ile yapılmalı?
PDO, veritabanı sürücülerinden bağımsızdır ve hazırlanan ifadeler (prepared statements) sayesinde SQL Injection saldırılarına karşı yerleşik koruma sağlar.
Anket sonuçlarını grafik olarak nasıl gösterebilirim?
Veritabanından COUNT() fonksiyonu ile verileri çekip, Chart.js gibi bir JavaScript kütüphanesi kullanarak dinamik grafikler oluşturabilirsiniz.
Bu sistemi nasıl daha hızlı hale getirebilirim?
Sık yapılan sorgular için Redis gibi önbellekleme (caching) araçlarını kullanabilir veya veritabanı tablolarınızda ilgili sütunlara indeks (index) ekleyebilirsiniz.
Dinamik anket sistemi mobil uyumlu olmalı mı?
Evet, anketler genellikle mobil cihazlardan doldurulur. CSS Framework'leri (Tailwind veya Bootstrap gibi) kullanarak form elemanlarını mobil uyumlu hale getirmelisiniz.
İleri Seviye Veri Analitiği ve Raporlama
Anket sisteminizden elde ettiğiniz verileri ham bir şekilde veritabanında tutmak yerine, bu verileri anlamlı istatistiklere dönüştürmek sistemin değerini artırır. Özellikle yöneticiler için verilerin yüzde dilimlerine ve toplam katılım sayılarına göre filtrelenmesi kritik bir ihtiyaçtır.
Aşağıdaki PHP fonksiyonu, belirli bir anket sorusu için sonuçları yüzde değerleri ile birlikte hesaplayan pratik bir örnektir:
function getAnketIstatistikleri($db, $soru_id) {
$sql = "SELECT secenek, COUNT(*) as oy_sayisi
FROM yanitlar
WHERE soru_id = :soru_id
GROUP BY secenek";
$stmt = $db->prepare($sql);
$stmt->execute(['soru_id' => $soru_id]);
$sonuclar = $stmt->fetchAll(PDO::FETCH_ASSOC);
$toplam_oy = array_sum(array_column($sonuclar, 'oy_sayisi'));
$istatistik = [];
foreach ($sonuclar as $row) {
$yuzde = ($toplam_oy > 0) ? ($row['oy_sayisi'] / $toplam_oy) * 100 : 0;
$istatistik[] = [
'secenek' => $row['secenek'],
'yuzde' => round($yuzde, 2)
];
}
return $istatistik;
}
Anket Sistemini Yayına Alma ve Ölçeklendirme
Geliştirdiğiniz sistemi yerel sunucudan canlı bir ortama taşırken (deployment), güvenlik ve performans ayarlarını gözden geçirmeniz gerekir. Canlı sunucularda hata ayıklama (debug) modunun kapalı olması, veritabanı şifrelerinin .env dosyalarında saklanması ve veritabanı sorgularının indekslenmesi temel gereksinimlerdir.
Veritabanı İndeksleme ile Performans Artışı
Anket katılımcı sayınız arttıkça, yanitlar tablosundaki sorgular yavaşlayabilir. soru_id sütunu üzerinde bir indeks oluşturmak, veritabanı motorunun veriyi tarama süresini ciddi oranda düşürür. İndeksleme işlemini veritabanı yönetim panelinizden veya SQL komutu ile şu şekilde yapabilirsiniz:
-- İndeks oluşturma komutu
CREATE INDEX idx_soru_id ON yanitlar(soru_id);
-- Sorgu performansını test etme
EXPLAIN SELECT * FROM yanitlar WHERE soru_id = 1;
Güvenlik İçin İleri İpuçları
- Rate Limiting: Aynı IP adresinden kısa sürede çok sayıda oy gönderilmesini engellemek için bir "Rate Limiter" mekanizması kurun.
- CSRF Koruması: Anket formlarınıza her oturum için benzersiz bir token ekleyerek, dışarıdan gelebilecek sahte form gönderimlerini (Cross-Site Request Forgery) engelleyin.
- Veri Doğrulama: Kullanıcıdan gelen yanıtların beklenen seçenekler dahilinde olup olmadığını mutlaka sunucu tarafında (server-side) tekrar kontrol edin.
Bu ek geliştirmeler, basit bir anket formunu profesyonel bir veri toplama aracına dönüştürmenize yardımcı olacaktır. Sisteminizin ölçeklenebilir olması için veritabanı bağlantılarını her istek sonunda düzgün bir şekilde kapatmayı ve bağlantı havuzlarını (connection pooling) optimize etmeyi unutmayın.
Sonuç
PHP ile veritabanı destekli bir dinamik anket sistemi kurmak, veritabanı etkileşimi, güvenlik önlemleri ve kullanıcı deneyimi gibi web geliştirmenin temel taşlarını kapsayan harika bir projedir. Bu rehberde öğrendiğiniz PDO kullanımı, SQL Injection koruması ve veri işleme teknikleri, daha karmaşık web uygulamaları geliştirmeniz için size sağlam bir temel oluşturacaktır.
Bir sonraki adım olarak, ankete katılım oranlarını analiz eden bir yönetici paneli ekleyebilir veya kullanıcıların anketi tamamladıktan sonra sonuçları görebileceği bir "Gerçek Zamanlı Sonuçlar" sayfası tasarlayabilirsiniz.


Yorumlar (17)
Eline sağlık Mert hocam, tam da böyle bir şeye ihtiyacım vardı. Kodlar gayet temiz görünüyor, hemen kendi projeme uyarlamaya çalışacağım.
Teşekkür ederim Caner, umarım projende sorunsuz çalışır. Takıldığın bir yer olursa sorabilirsin.
Ya ben veritabanı bağlantısında hata alıyom sürekli, her şeyi doğru yaptığımı düşünüyorum ama bi türlü çözemedim. Yardımcı olabilcek var mı?
Veritabanı kullanıcı bilgilerini config dosyasından kontrol ettin mi? Bazen şifredeki boşluklar bile sorun olabiliyor.
PDO yerine MySQLi kullanmak günümüzde ne kadar güvenli? Ben hep PDO tercih ediyorum, bu konuda bir değerlendirme yapabilir misin?
PDO kesinlikle daha esnek ve güvenli bir tercih. Bu rehberde yeni başlayanlar için daha anlaşılır olduğu için MySQLi kullandım, ancak profesyonel projelerde PDO şart.
Güzel çalışma ama güvenlik kısmına biraz daha değinebilirdin. SQL injection koruması için sadece prepared statements yeterli mi yoksa başka önlemler de almalı mıyız?
Haklısın Emre, input validasyonları ve XSS koruması da işin içine girince konu çok uzuyordu. Bir sonraki yazıda güvenlik katmanlarını detaylı işleyebilirim.
Harika bi yazı olmuş, anlatım çok sade ve anlaşılır. Teşekkürler paylaşım için.
Kod bloklarını kopyaladım ama çalışmadı. Acaba veritabanı tablosunu oluştururken bir şeyi atlamış olabilir miyim?
Tablo yapısını ve sütun isimlerini kontrol etmeni öneririm, bazen karakter kodlamaları bile sorun çıkarabiliyor.
baya iyi anlatmışsın ellerine sağlık, tamda aradığım sistemdi. bide buna oy verme kısıtlaması (ip adresiyle) eklesek nasıl olurdu?
IP ile sınırlama yaparsan aynı ağdan girenler birbirini engeller, bence cookie veya kullanıcı girişi şartı daha mantıklı.
Anlatım gayet başarılı, yeni başlayanlar için çok öğretici bir rehber olmuş. Başarılarının devamını dilerim.
Veritabanı bağlantı kodlarında hata var sanki, denedim ama hata veriyo. Kodların güncelliğini kontrol edermisiniz?
Kodlar güncel ve çalışır durumda, hata mesajını paylaşırsan sorunu daha hızlı çözebiliriz.
Basit ve etkili, teşekkürler.
Yorum Yaz