Php İle Pdo Kullanarak Veritabanı Bağlantısı Ve Güvenli Sorgu Nasıl Yapılır?

Php İle Pdo Kullanarak Veritabanı Bağlantısı Ve Güvenli Sorgu Nasıl Yapılır?
Php İle Pdo Kullanarak Veritabanı Bağlantısı Ve Güvenli Sorgu Nasıl Yapılır?

PHP ile PDO Kullanarak Veritabanı Bağlantısı ve Güvenli Sorgu Nasıl Yapılır?

PHP dünyasında modern ve güvenli bir veritabanı etkileşimi kurmak istiyorsanız, PDO (PHP Data Objects) kütüphanesi standart kabul edilir. PDO, farklı veritabanı sistemleri ile çalışmanıza olanak tanıyan, esnek ve SQL Injection saldırılarına karşı hazırlıklı bir veritabanı erişim katmanıdır. Bu rehberde, PHP ile PDO kullanarak veritabanı bağlantısı kurmayı ve güvenli sorgular yazmayı adım adım öğreneceksiniz.

Bu makale, PHP projelerinde veritabanı güvenliğini ön planda tutan geliştiriciler için hazırlanmıştır. Geleneksel mysql_* fonksiyonlarının artık kullanılmadığı 2026 yılında, PDO ile hata yönetimi ve hazırlanan ifadeler (prepared statements) kullanarak nasıl profesyonel bir yapı kuracağınızı detaylandıracağız.

Gereksinimler ve Ön Hazırlık

PDO ile çalışmaya başlamadan önce sisteminizde aşağıdaki bileşenlerin kurulu ve yapılandırılmış olması gerekir:

  • PHP Sürümü: En az 8.2 veya üzeri bir sürüm önerilir.
  • Veritabanı: MySQL veya MariaDB sunucusu.
  • PDO Eklentisi: PHP yapılandırmanızda pdo_mysql eklentisinin aktif olması gerekir.
  • Düzenleyici: VS Code veya benzeri bir IDE.

PHP'de PDO eklentisinin yüklü olup olmadığını kontrol etmek için terminalde php -m komutunu çalıştırabilir veya bir phpinfo() dosyası oluşturarak "PDO drivers" başlığını inceleyebilirsiniz.

Adım 1: PDO ile Veritabanı Bağlantısı Oluşturma

PDO bağlantısı kurarken veritabanı bilgilerini bir dizi veya değişkenler halinde tutmak, yönetimi kolaylaştırır. Bağlantı sırasında hata yönetimi için try-catch bloklarını kullanmak, veritabanı sunucusu kapalı olduğunda uygulamanızın çökmesini engeller.


$host = 'localhost';
$db   = 'proje_veritabani';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

try {
     $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
     throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

Yukarıdaki kodda PDO::ATTR_ERRMODE ayarını ERRMODE_EXCEPTION yaparak, hataların PHP tarafından yakalanabilir istisnalar olarak fırlatılmasını sağladık. Bu, hata ayıklama sürecini çok daha verimli kılar.

Adım 2: Güvenli Veri Okuma (SELECT Sorguları)

Veritabanından veri çekerken asla kullanıcıdan gelen veriyi doğrudan sorgu metnine eklemeyin. Bunun yerine "Prepared Statements" (Hazırlanmış İfadeler) yöntemini kullanmalısınız. Bu yöntem, SQL Injection saldırılarını engellemek için veriyi sorgu yapısından ayırır.


$id = 5;
$stmt = $pdo->prepare("SELECT kullanici_adi, email FROM kullanicilar WHERE id = :id");
$stmt->execute(['id' => $id]);
$kullanici = $stmt->fetch();

if ($kullanici) {
    echo "Kullanıcı Adı: " . htmlspecialchars($kullanici['kullanici_adi']);
}

Burada :id bir yer tutucudur (placeholder). execute metoduna gönderilen dizi, bu yer tutucunun değerini güvenli bir şekilde sorguya enjekte eder. htmlspecialchars fonksiyonu ise XSS (Cross-Site Scripting) saldırılarını önlemek için çıktıyı temizler.

Adım 3: Güvenli Veri Ekleme ve Güncelleme

Veri ekleme (INSERT) veya güncelleme (UPDATE) işlemleri de benzer bir mantıkla çalışır. Kullanıcı girdilerini doğrudan sorguya dahil etmek yerine, parametre bağlama yöntemini kullanmak sisteminizin güvenliğini sağlar.


$sql = "INSERT INTO kullanicilar (kullanici_adi, email) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(['ahmet_yildiz', 'ahmet@example.com']);

echo "Yeni kayıt ID: " . $pdo->lastInsertId();

Bu örnekte soru işareti (?) operatörünü kullandık. Parametreleri sırasıyla dizi içerisinde gönderdiğimizde, PDO veriyi veritabanına göndermeden önce güvenli bir şekilde temizler.

PDO Yöntemlerinin Karşılaştırılması

Yöntem Avantajı Dezavantajı
PDO (Hazırlanmış İfade) SQL Injection koruması, yüksek performans. Biraz daha fazla kod yazımı gerektirir.
mysqli (Geleneksel) Basit yapılı sorgular için hızlıdır. Güvenlik açığına daha meyillidir, esneklik düşüktür.

Adım 4: İşlem (Transaction) Yönetimi

Birden fazla veritabanı işleminin bir bütün olarak gerçekleşmesi gerektiği durumlarda (örneğin banka transferi), "Transaction" yapısı kullanılır. Eğer işlemlerden biri başarısız olursa, yapılan tüm değişiklikler geri alınır.


try {
    $pdo->beginTransaction();

    $pdo->exec("UPDATE hesaplar SET bakiye = bakiye - 100 WHERE id = 1");
    $pdo->exec("UPDATE hesaplar SET bakiye = bakiye + 100 WHERE id = 2");

    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Hata oluştu, işlemler geri alındı: " . $e->getMessage();
}

Bu yöntem, veritabanı bütünlüğünü korumak için kritiktir. beginTransaction ile süreci başlatır, hata durumunda rollBack ile veritabanını eski haline döndürürüz.

Kritik Güvenlik Uyarısı: Veritabanı şifrelerinizi asla kaynak kod içerisinde açıkça bırakmayın. Üretim ortamında (production) bu bilgileri bir .env dosyasında tutun ve getenv() veya bir kütüphane aracılığıyla okuyun. Ayrıca, hata mesajlarını son kullanıcıya göstermeyin; hataları bir log dosyasında tutun.

Sıkça Sorulan Sorular

PDO neden MySQLi'den daha iyidir?

PDO, veritabanından bağımsız bir yapı sunar. Yani kodunuzu değiştirmeden PostgreSQL veya SQLite'a geçiş yapabilirsiniz. Ayrıca daha gelişmiş hata yönetimi ve güvenlik özellikleri sunar.

SQL Injection nedir ve PDO nasıl önler?

SQL Injection, saldırganın giriş alanlarına kötü niyetli SQL komutları yazarak veritabanına sızmasıdır. PDO, "prepared statements" kullanarak veriyi sorgu komutundan ayırır, böylece veritabanı girdiyi komut olarak değil, sadece veri olarak işler.

Fetch metotları arasındaki fark nedir?

fetch() tek bir satır döndürürken, fetchAll() tüm sonuçları bir dizi olarak getirir. PDO::FETCH_ASSOC ise sonuçları anahtar-değer çiftleri (sütun adı => değer) şeklinde almanızı sağlar.

Bağlantı hatalarını nasıl yönetmeliyim?

Her zaman try-catch bloğu kullanın. Hata mesajını kullanıcıya göstermek yerine, veritabanı bağlantı hatasını log dosyasına yazdırın ve kullanıcıya "Sistemde geçici bir sorun oluştu" gibi genel bir mesaj verin.

Prepared statement kullanırken nelere dikkat etmeliyim?

Parametrelerin doğru sırayla gönderildiğinden emin olun. İsimlendirilmiş parametreler (:isim gibi) kullanmak, büyük sorgularda hata yapmanızı azaltır.

PDO ile Hata Ayıklama ve Loglama Stratejileri

Veritabanı işlemlerinde hata yönetimi, uygulamanın kararlılığı için kritik bir öneme sahiptir. PDO, varsayılan olarak hataları sessizce geçiştirebilir veya PDO::ERRMODE_SILENT modunda çalışabilir. Üretim ortamında kullanıcıya hata detaylarını göstermek güvenlik zafiyeti oluştururken, geliştirme aşamasında bu hataları görmek hayati önem taşır.

En iyi uygulama, PDO bağlantısını oluştururken hata modunu ERRMODE_EXCEPTION olarak ayarlamak ve veritabanı işlemlerini try-catch blokları içerisine almaktır.

try {
    $pdo = new PDO("mysql:host=localhost;dbname=test_db", "kullanici", "sifre", [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]);
} catch (PDOException $e) {
    // Hata detaylarını log dosyasına yazın, kullanıcıya genel bir mesaj verin
    error_log("Veritabanı bağlantı hatası: " . $e->getMessage());
    die("Üzgünüz, şu anda veritabanına bağlanılamıyor.");
}

Hataları loglarken error_log() fonksiyonunu kullanarak sunucu tarafında bir kayıt tutmak, canlı sistemlerde meydana gelen sorunları analiz etmenizi kolaylaştırır. Asla $e->getMessage() çıktısını doğrudan tarayıcıya yansıtmayın; bu, veritabanı yapınızın ifşa olmasına neden olabilir.

PDO Performansını Optimize Etme İpuçları

PDO, veritabanı etkileşimlerinde oldukça hızlıdır ancak büyük ölçekli uygulamalarda bazı optimizasyonlar performansı ciddi oranda artırabilir. Özellikle hazırlanan ifadelerin (prepared statements) tekrar kullanımı, veritabanı sunucusunun sorgu planı oluşturma yükünü azaltır.

1. Persistent Connections (Kalıcı Bağlantılar)

Kalıcı bağlantılar, her sayfa isteğinde yeni bir veritabanı bağlantısı açmak yerine, mevcut bağlantının açık kalmasını sağlar. Bu, yüksek trafikli sitelerde bağlantı kurma maliyetini düşürür.

$options = [
    PDO::ATTR_PERSISTENT => true,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
$pdo = new PDO($dsn, $user, $pass, $options);

2. Gereksiz Veri Çekiminden Kaçınma

SELECT * kullanmak yerine, yalnızca ihtiyacınız olan sütunları belirtin. Bu, hem ağ trafiğini azaltır hem de PHP tarafında bellek kullanımını optimize eder. Ayrıca, büyük veri setleriyle çalışırken fetchAll() yerine fetch() kullanarak verileri döngü içerisinde satır satır işlemek, bellek (RAM) tüketimini minimize eder.

$stmt = $pdo->prepare("SELECT id, baslik FROM makaleler WHERE durum = :durum");
$stmt->execute(['durum' => 1]);

while ($row = $stmt->fetch()) {
    echo $row['baslik'] . "
"; }

3. İndeksleme Kontrolü

PDO ne kadar hızlı olursa olsun, veritabanı tarafında indekslenmemiş bir tabloda yapılan sorgu yavaş kalacaktır. EXPLAIN komutunu kullanarak sorgularınızın nasıl çalıştığını analiz edin ve sık kullanılan sütunlara indeks eklediğinizden emin olun.

Strateji Avantajı
Kalıcı Bağlantı Bağlantı açılış süresini azaltır.
Satır Satır Fetch Düşük bellek kullanımı sağlar.
Sütun Seçimi Veri transferini hızlandırır.

Sonuç

PHP ile PDO kullanarak veritabanı bağlantısı kurmak ve güvenli sorgular yazmak, modern web geliştirmenin temel taşıdır. Bu rehberde öğrendiğiniz "prepared statements" ve "transaction" yapıları, projelerinizi hem daha performanslı hem de siber saldırılara karşı daha dirençli hale getirecektir. Bir sonraki adım olarak, veritabanı işlemlerini daha modüler hale getirmek için bir "Repository" tasarım deseni oluşturmayı deneyebilirsiniz.

Sorumluluk Reddi: Bu makalede paylaşılan kodlar eğitim amaçlıdır. Uygulamanızın güvenliğinden yazılımcı olarak siz sorumlusunuz. Üretim ortamına geçmeden önce tüm girdileri doğrulamalı (validate) ve uygun yetkilendirme kontrollerini yapmalısınız.
Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Sürdürülebilir yaşam ve pratik ev yönetimi üzerine içerik stratejileri geliştiriyorum. Yalın anlatımı ve uygulanabilirliği ön planda tutan bir yazı dilim var.

Yorumlar (0)

Yorum Yaz