PHP Veri Nesneleri (PDO) eklentisi, veritabanı işlemlerini gerçekleştirmek için sunulan bir arayüzdür. Php’nin v5.5 sürümünden itibaren mysql_ şeklinde tanımladığımız fonksiyonlara destek vermemesi nedeniyle, veritabanı işlemlerini PDO veya Mysqli ile yapmak zorundayız. Bizlere sunulan bu iki alternatifin birbirine göre avantajları olduğu durumlar bulunmaktadır. Bunlar;
PDO | Mysqli |
Sadece nesne yönelimli kullanılır | Nesne yönelimsiz de kullanılabilir |
12 farklı veritabanını ile kullanılabilir | Sadece MySQL ile kullanılır |
SQL Injection korumalıdır | SQL Injection kontrolünü yazılımcı yapılmalıdır |
İsimlendirilmiş parametreyi destekler | İsimlendirilmiş parametreyi desteklemez |
Hız konusunda Mysqli’den yavaştır | PDO’dan %5 civarı daha performanslıdır |
temel olarak yukarıdaki şekildedir diyebiliriz. Ben daha önce “Nesne Yönelimli Programla (OOP)” ile anlatım yapmayı tercih edeceğimi söylediğim için, buna ek olarak da uygulamalarımda PDO’yu tercih ettiğimden (MsSQL için de kullanıyorum ve SQL Injection kontrolünü yapmama gerek kalmıyor), bu yazım sadece PDO’nun temel kullanımı ile ilgili olacaktır. Eğer Mysqli kullanmayı seçecekler varsa, kullanımında mysql_ fonksiyonlarından pek bir fark bulunmuyor. Bu arada, Php sürümünüz v5 altındaysa bu eklentileri kullanamazsınız. Bu önemli notu da ekledikten sonra artık PDO’nun temel fonksiyonlarının kullanımını anlatmaya geçebiliriz.
<?php class baglan{ //veritabanı bilgileri const host = 'localhost'; const user = 'root'; const pass = ''; const db = 'pdo'; public $conn; public function __construct(){ //açılışta çalıştır $this->dbBaglantiKur(); } public function dbBaglantiKur(){ //veritabanı bağlantısı kurma try{ $this->conn = new PDO("mysql:dbname=".self::db.";host=".self::host, self::user, self::pass); $this->conn->query("SET NAMES 'utf8'"); $this->conn->query('set character set utf8'); }catch(PDOException $e){ die($e->getMessage()); } } public function dbOlustur(){ //pdo adlı veritabanında yazilar adlı tablo açma $sql = "CREATE TABLE IF NOT EXISTS `yazilar`( `id` INT AUTO_INCREMENT NOT NULL, `baslik` varchar(100) NOT NULL, `icerik` varchar(400), PRIMARY KEY (`id`) )"; $olustur = $this->conn->prepare($sql); return $olustur->execute(); } public function dbVerileriEkle(){ //yazılar tablosuna kayıt ekleme (siralı parametre) $yazilar = array('1. yazının başlığı','1. içerik', '2. başlık','2. içerik', '3. başlık','3. içerik'); $ekle = $this->conn->prepare('INSERT INTO yazilar (baslik,icerik) VALUES (?,?),(?,?),(?,?)'); return $ekle->execute($yazilar); } public function dbSonKayitIdAl(){ //son kayıt id değeri !(bu bağlantıda ekleme işlemi yapılmışsa) return $this->conn->lastInsertId(); } public function dbVerileriSay(){ //kayıt sayısını bulma $say = $this->conn->prepare('SELECT id FROM yazilar'); $say->execute(); return $say->fetchColumn(); } public function dbVerileriCek(){ //bütün verileri alma $veriler = $this->conn->prepare('SELECT id,baslik,icerik FROM yazilar'); $veriler->execute(); return $veriler->fetchAll(PDO::FETCH_ASSOC); } public function dbVeriyiCek($id){ //sadece bir kayıtı (parametredeki) alma $veri = $this->conn->prepare('SELECT id,baslik,icerik FROM yazilar WHERE id=?'); $veri->execute(array($id)); return $veri->fetch(PDO::FETCH_ASSOC); } public function dbVerilerdeAra($aranan){ //kayıtlarda arama yapma $bul = $this->conn->prepare('SELECT id,baslik,icerik FROM yazilar WHERE baslik LIKE ?'); $bul->execute(array('%'.$aranan.'%')); return $bul->fetchAll(PDO::FETCH_ASSOC); } public function dbVeriyiGuncelle($id){ //parametredeki veriyi güncelleme (isimlendirilmiş parametre) $guncelle = $this->conn->prepare('UPDATE yazilar SET baslik = :baslik WHERE id = :id'); return $guncelle->execute(array('baslik' => 'bu başlığı değiştirdim', 'id' => $id)); } public function dbVeriyiSil($id){ //parametredeki kayıtı silme $sil = $this->conn->prepare('DELETE FROM yazilar WHERE id=?'); return $sil->execute(array($id)); } public function __destruct(){ //bağlantıyı sonlandırma $this->conn = null; } } //örnek kullanım $baglanti = new baglan; $baglanti->dbVerileriEkle(); echo $baglanti->dbSonKayitIdAl(); ?>
Yukarıda PDO’nun temel kullanımını gösterdim. PDO’nın başka bir çok methodu bulunmakta, eğer bunları incelemek isterseniz Php.net adresini önerebilirim. SQL Injection sorunundan korunmak için mutlaka prapared statements kullanın. Ayrıca, aldığınız parametrelerde bulunabilme ihtimali olan Html etiketlerini (<script></script>) temizlemeyi unutmayın, çünkü prapared statements XSS açığını önlemez.
Bu yorum 29 Aralık 2013 tarihinde 16:18 sularında yazılmıştır.
Sql injection açığından çok çekiyoruz, öğrendiğim iyi oldu.
Bu yorum 30 Aralık 2013 tarihinde 14:04 sularında yazılmıştır.
Ben bunu sql gönderilen bir sınıfa çevirip kullanmayı düşünüyorum, neredeyse bütün sorgu tipleri var, eline sağlık bu arada. Dönüşünü sabırsızlıkla bekliyordum.
Bu yorum 02 Ocak 2014 tarihinde 22:19 sularında yazılmıştır.
XSS Açıgını Engelleyecek Bir Fonksiyon Öneriyormusunuz
Veritabına Post Ederken
$baslik= mysql_real_escape_string($_POST[‘baslik’]);
Böyle Kullanıyordum, PDO’da Sadece XSS Açıgını Önlemem Yeterli Olacakmı ?
Bu yorum 03 Ocak 2014 tarihinde 09:15 sularında yazılmıştır.
Yukarıdaki kullanım XSS açığını önlemez (mysql_real_escape_string XSS açığını değil Sql injection açığını engeller). XSS açığını önlemek için strip_tags kullanman gerekir.
Bu yorum 03 Ocak 2014 tarihinde 09:18 sularında yazılmıştır.
strip_tags ya da htmlentities kullan
Bu yorum 03 Ocak 2014 tarihinde 22:42 sularında yazılmıştır.
@Ayhan @Mustafa Kolcu İkinizede Çok Teşekkür Ederim
Bu yorum 08 Ocak 2014 tarihinde 12:47 sularında yazılmıştır.
Post kontrolünü strip_tags ile yaptığımda yazılara link vs atanmıyor, bunu nasıl kullanmam gerekir?
Bu yorum 08 Ocak 2014 tarihinde 17:11 sularında yazılmıştır.
Silmeyip sadece zararsız hale getirtebilirsin, htmlentities ya da htmlspecialchars kullanarak. Hiç olmadı kendi fonksiyounu yazarsın istemediğin etiketleri temizleyen. Detaylı olarak bu konuları incelemek istersen güvenlik açıklarını kapatma yazımdan faydalanabilirsin.
Bu yorum 12 Ocak 2014 tarihinde 16:14 sularında yazılmıştır.
Merhaba, PDO’da execute ilemi yoksa bindParam ilemi verileri kayıt etmek daha doğrudur?
Bu yorum 12 Ocak 2014 tarihinde 17:06 sularında yazılmıştır.
Güvenlik açısından aralarında fark yok, prepared statements ile kullanılırsa ikisi de güvenlidir. Fakat bindParam ile gönderdiğimiz verilere (GET, POST metodu ile gelen verilerde daha çok tercih ediliyor) veri tipi uygulayabiliyoruz (PDO::PARAM_INT gibi). Ayrıca SQL LIMIT sorgusunu dinamik olarak belirliyorsanız (LIMIT mikarını dışarıdan gönderilen parametre aracılığıyla) bindParam kullanmak daha avantajlı çünkü execute kullandığınızda SQL sorgusunu string ifadeye (LIMIT ’10’ gibi) çeviriyor, bundan dolayı da hata meydana geliyor, bindParam’da veri tipini tanımlarsanız (PDO::PARAM_INT olarak), integer değer olarak göreceğinden hata meydana gelmez.
Bu yorum 08 Ocak 2014 tarihinde 20:30 sularında yazılmıştır.
Kodların Silineceğini Unuttum Pardon 🙂
https://gist.github.com/canaytekin/ce75ea90036f1f55458e
Yukarıdaki Linkten Bakabilirsiniz.
Bu yorum 09 Ocak 2014 tarihinde 09:24 sularında yazılmıştır.
PDO’nun fetchAll ile bir seferde bütün verileri alma kolaylığı çok hoşuma gidiyor, bir daha while gibi döngü kurmaya gerek bırakmıyor.
Bu yorum 07 Şubat 2014 tarihinde 15:21 sularında yazılmıştır.
Artık yeni sürümlerde destek verilmeyecek olması PDO öğrenimini mecbur kıldı. Biz de mecburen öğreneceğiz.
Bu yorum 08 Şubat 2014 tarihinde 16:56 sularında yazılmıştır.
Haklısın ben de bu yüzden öğrenmek istedim ama Sql Injection önlemesi büyük avantaj olmuş.
Bu yorum 12 Şubat 2014 tarihinde 20:16 sularında yazılmıştır.
Object mapping özelliği de bulunmakta benim favorim.
Bu yorum 24 Mart 2014 tarihinde 10:24 sularında yazılmıştır.
Hocam bu örneği bir de form üzerinde yapmanız mümkün mü acaba, araştırdım ama örnek bulamadım. Form ile kayıt, düzenleme, ve vt’den verileri çekme gibi.
Bu yorum 27 Mart 2014 tarihinde 13:58 sularında yazılmıştır.
Bu örneği daha önce yazdığım GET ve POST işlemleri örneğiyle birleştirirsen, istediğini elde edersin. Örneğin, arama işlemi yapmak için; $ara=$_POST[‘ara’]; şeklinde formdan değeri alıp, $baglanti->dbVerilerdeAra($ara); ile sınıfa göndermek.
Bu yorum 16 Aralık 2014 tarihinde 19:13 sularında yazılmıştır.
Hocam ya bir karar vereceğim artık diyorlar ki PDO güvenli olmayabilir en iyisi Laravele geçin diyorlar. Lütfen artık neye güveneceğim bilmiyorum :((( hem de geliştirme aşamasındayım!.
Bu yorum 16 Aralık 2014 tarihinde 20:56 sularında yazılmıştır.
PDO en güvenli yöntem (prapered statements kullanırsan). Laravel’de PDO kullanıyor bu arada.
Bu yorum 21 Ocak 2015 tarihinde 13:23 sularında yazılmıştır.
Merhaba,
Pdo olarak yazdığım sistemlerde yeni fark ettiğim bir sorun oluyor. Textareadan resim gönderildiğinde (boşluklar yok) olarak kaydediyor ve çağırırken sıkıntı yaratıyor. Bunu kaynağı pdo sanırım. Bir bilginiz var mi?
Bu yorum 16 Şubat 2015 tarihinde 11:04 sularında yazılmıştır.
Boşlukların olmaması PDO ile alakalı değil kaydetme ve ekranda gösterme şeklinizle alakalıdır. Örneğin; textareadan yazılar arasında kullanılan alt satıra inme (enter) tuşunun ekranda o şekilde gösterilmesini isterseniz nl2br($str) fonksiyonunu kullanabilirsiniz.
Bu yorum 16 Nisan 2015 tarihinde 12:54 sularında yazılmıştır.
bindParam örneği de ekleseydiniz tadından yenmez bit yazı olurdu ama yine bütün örnek tiplerine değinmişsiniz. Baya işimi gördü teşekkürler.