Merhaba Webkolog takipçileri!
Bugün sizlere PHP dünyasında veritabanı işlemlerini daha güvenli, esnek ve modern bir şekilde yapmamızı sağlayan PDO (PHP Data Objects) hakkında detaylı bir makale hazırladım. Artık MySql uzantısı gibi eskide kalmış yöntemler yerine, PDO kullanarak farklı veritabanı sistemleriyle kolayca iletişim kurabilir, uygulamalarınızı SQL enjeksiyon saldırılarına karşı çok daha güçlü hale getirebilirsiniz.
PDO Neden Önemli?
PDO, PHP'nin bir veritabanı soyutlama katmanıdır. Bu, temelde şu anlama gelir:
- Veritabanı Bağımsızlığı: Kodunuzu farklı bir veritabanına taşımak istediğinizde (örneğin MySQL'den PostgreSQL'e), PDO sayesinde çok daha az kod değişikliğiyle bu geçişi yapabilirsiniz. Çünkü PDO, her veritabanı için aynı arayüzü sunar.
- Güvenlik (SQL Enjeksiyonuna Karşı Koruma): PDO'nun en büyük avantajlarından biri, hazırlanmış deyimler (prepared statements) ve parametre bağlama (parameter binding) yetenekleridir. Bu özellikler, kullanıcıdan gelen verileri doğrudan SQL sorgusuna eklemek yerine, güvenli bir şekilde işleyerek SQL enjeksiyonu gibi ciddi güvenlik açıklarının önüne geçer.
- Hata Yönetimi: PDO, veritabanı işlemlerinde oluşan hataları daha tutarlı ve anlaşılır bir şekilde yönetmek için istisnaları (exceptions) kullanır. Bu da hata ayıklama süreçlerini kolaylaştırır.
Veritabanı Bağlantısı
PDO ile bir veritabanına bağlanmak oldukça basittir. Genellikle bir try-catch
bloğu içinde yapılır ki olası bağlantı hataları yakalanabilsin:
try {
// MySQL veritabanına bağlantı örneği
$db = new PDO("mysql:host=localhost;dbname=denedb", "root", "123456");
// Hata modunu ayarlama (isteğe bağlı ama önerilir)
// PDO::ERRMODE_EXCEPTION: Hatalar istisna olarak fırlatılır (önerilen)
// PDO::ERRMODE_WARNING: Hatalar PHP uyarısı olarak gösterilir
// PDO::ERRMODE_SILENT: Hatalar sessizce geçiştirilir (genellikle istenmez)
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Veritabanı bağlantısı başarıyla kuruldu!";
} catch (PDOException $e) {
// Bağlantı hatası oluşursa mesajı yazdır
echo "Bağlantı Hatası: " . $e->getMessage();
}
Karakter setini ayarlamak, özellikle Türkçe karakterlerin doğru gösterilmesi için önemlidir. Bunu DSN (Data Source Name) içinde veya bağlantıdan sonra exec()
metodu ile yapabilirsiniz:
// DSN içinde karakter setini ayarlama (önerilen yol)
$db = new PDO("mysql:host=localhost;dbname=test;charset=utf8", "root", "123456");
// Veya bağlantıdan sonra exec() ile ayarlama (DSN ile beraber kullanmaya gerek yoktur)
$db->exec("set names utf8");
// Daha spesifik bir sıralama için
$db->exec("set names utf8 COLLATE utf8_turkish_ci");
Veritabanı bağlantısını sonlandırmak için, PDO nesnesini null
olarak atamanız yeterlidir:
$db = null; // Veritabanı bağlantısı kapatılır
Sorgu Yöntemleri: query() ve prepare()
PDO'da sorgu çalıştırmanın iki temel yolu vardır: query()
ve prepare()
.
query() Yöntemi (Güvenli Parametre Geliyorsa Kullanın)
query()
metodu, genellikle parametre içermeyen veya güvenliğinden emin olduğunuz statik SQL sorguları için kullanılır. PDOStatement
nesnesi döndürür.
// Tüm kullanıcıları seçen basit bir sorgu
$sth = $db->query("SELECT id, ad, soyad FROM kullanicilar", PDO::FETCH_ASSOC); // PDOStatement döndürür
// Tek sütun ve satır almak
$kullanici_sayisi = $db->query("SELECT COUNT(*) FROM kullanicilar")->fetchColumn();
echo "Toplam kullanıcı sayısı: " . $kullanici_sayisi . "<br>";
// Tek bir satır almak (dizi olarak)
$ilk_kullanici = $sth->fetch(PDO::FETCH_NUM); // Sütun numaralarına göre indisli dizi
echo "İlk kullanıcı ID: " . $ilk_kullanici[0] . ", Ad: " . $ilk_kullanici[1] . "<br>";
// Tüm satırları almak (çok boyutlu dizi olarak)
$tum_kullanicilar = $sth->fetchAll(PDO::FETCH_ASSOC); // Sütun isimlerine göre indisli dizi
foreach ($tum_kullanicilar as $kullanici) {
echo $kullanici['ad'] . " " . $kullanici['soyad'] . "<br>";
}
prepare() Yöntemi (Parametre Koruması İçin Şiddetle Tavsiye Edilir)
Kullanıcıdan gelen veri içeren dinamik sorgularda mutlaka prepare()
metodunu kullanmalısınız. Bu yöntem, SQL enjeksiyonuna karşı en etkili korumadır. Sorgunuzu hazırlarsınız ve daha sonra parametreleri bağlarsınız.
Parametre Bağlama Yöntemleri:
1. İsimlendirilmiş Parametreler (:parametre_adı):
$yas = 30;
$cins = 'Erkek';
$sth = $db->prepare("SELECT * FROM kullanicilar WHERE yas = :yas AND cinsiyet = :cins");
// bindParam(): Değişken referansını bağlar
$sth->bindParam(':yas', $yas, PDO::PARAM_INT); // PDO::PARAM_INT, verinin integer olduğunu belirtir
$sth->bindParam(':cins', $cins, PDO::PARAM_STR, 12); // Son parametre isteğe bağlıdır (maksimum uzunluk)
$sth->execute();
$sonuclar = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($sonuclar);
2. Soru İşaretli Parametreler (?):
$yas = 25;
$cins = 'Kadın';
$sth = $db->prepare("SELECT * FROM kullanicilar WHERE yas = ? AND cinsiyet = ?");
// bindParam(): Parametre indeksini kullanarak değişken referansını bağlar
$sth->bindParam(1, $yas); // İlk soru işaretine $yas değişkeni
$sth->bindParam(2, $cins); // İkinci soru işaretine $cins değişkeni
$sth->execute();
$sonuclar = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($sonuclar);
3. bindValue() ile Parametre Bağlama:
bindValue()
, değişkenin anlık değerini bağlar, bindParam()
ise değişkenin referansını bağlar. Genellikle bindValue()
daha sık kullanılır.
$yas_degeri = 40;
$cinsiyet_degeri = 'Erkek';
// İsimlendirilmiş parametreler ile
$sth = $db->prepare("SELECT * FROM kullanicilar WHERE yas = :yas AND cinsiyet = :cins");
$sth->bindValue(':yas', $yas_degeri, PDO::PARAM_INT);
$sth->bindValue(':cins', $cinsiyet_degeri, PDO::PARAM_STR);
$sth->execute();
// Soru işaretli parametreler ile
$sth = $db->prepare("SELECT * FROM kullanicilar WHERE yas = ? AND cinsiyet = ?");
$sth->bindValue(1, $yas_degeri);
$sth->bindValue(2, $cinsiyet_degeri);
$sth->execute();
4. execute() içinde Parametreleri Geçme (En Pratik Yöntem):
Bu, genellikle en pratik ve en çok tercih edilen yöntemdir. execute()
metoduna bir dizi olarak parametreleri geçersiniz.
// İsimlendirilmiş parametreler ile
$sth = $db->prepare("SELECT * FROM kullanicilar WHERE yas = :yas AND cinsiyet = :cins");
$sth->execute(array('yas' => 30, 'cins' => 'Erkek'));
// Soru işaretli parametreler ile
$sth = $db->prepare("SELECT * FROM kullanicilar WHERE yas = ? AND cinsiyet = ?");
$sth->execute(array(30, 'Erkek'));
$sonuclar = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($sonuclar);
Sonuçları İşleme (fetch, fetchAll, fetchColumn)
Sorgunuzu çalıştırdıktan sonra sonuçları almak için çeşitli yöntemler kullanabilirsiniz:
fetch()
: Sonuç kümesindeki bir sonraki satırı döndürür. Döndürülen satırın formatını (dizi, nesne vb.) belirtebilirsiniz.fetchAll()
: Sonuç kümesindeki tüm satırları bir dizi olarak döndürür.fetchColumn()
: Sonuç kümesindeki tek bir sütunu (ve tek bir satırı) döndürür. Hangi sütunu istediğinizi indeks numarası ile belirtebilirsiniz (varsayılan 0).
Döndürme Tarzları (PDO::FETCH_* Sabitleri):
PDO::FETCH_ASSOC
: Sütun isimlerine göre indisli bir dizi döner. (Örn:$row['kullanici_adi']
)PDO::FETCH_NUM
: Sütun numaralarına göre indisli bir dizi döner. İlk sütunun indisi 0'dır. (Örn:$row[0]
)PDO::FETCH_BOTH
(varsayılan): Hem sütun isimlerine hem de sütun numaralarına göre indislenmiş bir dizi döner.PDO::FETCH_OBJ
: Özellik isimlerinin sütun isimlerine denk düştüğü anonim bir nesne örneği döndürür. (Örn:$row->kullanici_adi
)PDO::FETCH_CLASS
: Belirtilen sınıfın bir örneğini döndürür ve sütun değerlerini sınıfın özelliklerine eşler. Bu, özellikle veri modeli sınıflarınız varsa çok kullanışlıdır.
Örnek Kullanım (FETCH_CLASS):
class Uye {
public $ad;
public $soyad;
public function adSoyadGetir() {
return $this->ad . " " . $this->soyad;
}
}
$sth = $db->prepare("SELECT ad, soyad FROM kullanicilar");
$sth->execute();
// Sonuçları Uye sınıfının örnekleri olarak al
$sth->setFetchMode(PDO::FETCH_CLASS, "Uye");
foreach ($sth as $uye) {
echo $uye->adSoyadGetir() . "<br>";
}
Diğer Faydalı PDO Metotları
$db->lastInsertId()
: Son eklenen kaydın ID'sini döndürür.$sth->errorInfo()
: Son çalıştırılan sorguyla ilgili hata bilgilerini içeren bir dizi döndürür.$sth->execute()
: Bir prepared statement'ı çalıştırır ve başarılı isetrue
, değilsefalse
döndürür.
PDO::PARAM_* Sabitleri:
bindParam()
ve bindValue()
gibi metotlarda kullanabileceğiniz veri tipi sabitleridir:
PDO::PARAM_BOOL
: Boolean veri tipi.PDO::PARAM_NULL
: SQL NULL veri tipi.PDO::PARAM_INT
: SQL INTEGER veri tipi.PDO::PARAM_STR
: SQL CHAR, VARCHAR veya diğer string veri tipi.PDO::PARAM_LOB
: SQL büyük obje (binary large object) veri tipi.
PDO, PHP ile veritabanı etkileşimlerinizde size büyük bir esneklik ve güvenlik sağlar. Modern web uygulamaları geliştirirken PDO'yu kullanmak, hem sizin hem de kullanıcılarınızın güvenliği için kritik öneme sahiptir.
Umarım bu makale, PDO'nun temellerini anlamanıza ve projelerinizde güvenle kullanmaya başlamanıza yardımcı olmuştur. Unutmayın, güvenlik ve temiz kod her zaman önceliğimiz olmalı!
Webkolog'u takipte kalın!
Hepinize bol kodlu ve başarılı projeler dilerim!
0 yorum:
Yorum Gönder