PDO Kullanımı

Bildiğiniz gibi artık PHP veritabanı işlemleri için doğrudan mysql_ li fonksiyonların kullanımını tavsiye etmiyor. Bunun yerine şuan için önerdiği 2 farklı veritabanı eklentisi mevcut. Bunlardan bir tanesi mysqli, bir diğeri ise PDO.

Ben bu yazımda sizlere PDO’yu mysql_ fonksiyonlarına eş değer olacak şekilde anlatmaya çalışacağım. Eminim daha iyi anlayacaksınız.. Hazırsanız başlayalım?

Veritabanı Bağlantısı

mysql_ li fonksiyonlara veritabanına bağlantısı;

<?php
$baglanti = mysql_connect("localhost","root","123456") or die ();
mysql_select_db("test", $baglanti) or die ( mysql_error() );
?>

PDO da veritabanı bağlantısı;

<?php
try {
     $db = new PDO("mysql:host=localhost;dbname=test", "root", "123456");
} catch ( PDOException $e ){
     print $e->getMessage();
}
?>

Elbette PDO ile bağlanırken try ~ catch yapısını kullanmak zorunda değildik ancak böyle bir kullanım çok daha kullanışlıdır. Çünkü PDO’nun hatalar için bir exception’ı var ve daha mantıklı hata mesajları üretiyor.

Not: PDO sadece mysql’i değil bir çok veritabanı yapısını destekler. Ancak ben bu makalede sadece mysql ile ilgili anlatım yapacağım.

Karakter Setini Ayarlama

Her zaman bir charset belirlemek iyidir. Bunuda mysql_ li fonksiyonlarda ve PDO da nasıl yaptığımızı örneklerle öğrenelim;

mysql_ li fonksiyonlarda karakter setini ayarlama;

mysql_set_charset("utf8");

ya da

mysql_query("SET CHARACTER SET utf8");

PDO da karakter setini ayarlama;

$db = new PDO("mysql:host=localhost;dbname=test;charset=utf8", "root", "123456");

ya da;

$db->query("SET CHARACTER SET utf8");

SELECT İşlemi (Toplu)

mysql_ li fonksiyonlarda select işlemi;

$query = mysql_query("SELECT * FROM uyeler");
if ( mysql_affected_rows() ){
     while ( $row = mysql_fetch_assoc($query) ){
           print $row['kullanici_adi']."<br />";
     }
}

PDO da select işlemi;

$query = $db->query("SELECT * FROM uyeler", PDO::FETCH_ASSOC);
if ( $query->rowCount() ){
     foreach( $query as $row ){
          print $row['kulanici_adi']."<br />";
     }
}

SELECT İşlemi (Tek)

Sadece bir veriyi çekmek için nasıl bir işlem yapacağımızı görelim;

mysql_ li fonksiyonlarda tekil select işlemi;

$id = $_GET['id'];
$query = mysql_query("SELECT * FROM uyeler WHERE uye_id = '{$id}'");
if ( mysql_affected_rows() ){
    $row = mysql_fetch_assoc($query);
    print_r($row);
}

PDO da tekil select işlemi;

$id = $_GET['id']; 
$query = $pdo->query("SELECT * FROM uyeler WHERE uye_id = '{$id}'")->fetch(PDO::FETCH_ASSOC);
if ( $query ){
    print_r($query);
}

Her iki şekilde de güvenli bir select işlemi olmadı. Çünkü SQL Injection dediğimiz bir olay var ve şuan her iki işlem içinde kolayca uygulanabilir durumda. Bunun hakkında makale sonlarında güvenlik bölümünde sizlere bahsedeceğim.

INSERT İşlemi

Veritabanına veri kayıt etmek için mysql_ li fonksiyonlarla PDO arasındaki farkı görelim;

mysql_ li fonksiyonlarda insert işlemi;

$insert = mysql_query("INSERT INTO uyeler SET
uye_kadi  = 'Tayfun Erbilen',
uye_sifre = '123456',
uye_eposta = [email protected]'");
if ( $insert ){
     $last_id = mysql_insert_id();
     print "insert işlemi başarılı!";
}

PDO da insert işlemi;

$query = $db->prepare("INSERT INTO uyeler SET
uye_kadi = ?,
uye_sifre = ?,
uye_eposta = ?");
$insert = $query->execute(array(
     "Tayfun Erbilen", "123456", "[email protected]"
));
if ( $insert ){
    $last_id = $db->lastInsertId();
    print "insert işlemi başarılı!";
}

Her iki şekilde de veritabanına yeni bir veri kaydı yapılır. PDO kodları biraz uzun gibi görünsede daha güvenilirdir. Çünkü bu 2 kod parçacığında mysql_ li fonksiyonlu örnekte SQL Injection açığı mevcuttur. Unutmamak gerek ki insert işlemlerinin %99’u kullanıcıdan aldığımız veriler doğrultusunda olmakta. Buda alınan verilerin kontrol edilmesi anlamına gelir. Bunu siz yapmaktansa kullandığınız veritabanı sınıfının yapması çok daha kullanışlı olacaktır. PDO’da bunu sizin için yapıyor ve kullanıcıdan aldığınız bilgileri bu kullanım ile daha güvenilir hale getiriyor. Böylece SQL Injection açıklarından korunmuş oluyoruz.

Ayrıca PDO örneğinde ? yerine key (anahtar) isimler belirtipte ona göre dizide değer gönderebilirdik.. Yani şu şekilde bir örnekte yapabilirdik;

$query = $db->prepare("INSERT INTO uyeler SET
uye_kadi = :kadi,
uye_sifre = :sifre,
uye_eposta = :eposta");
$insert = $query->execute(array(
      "sifre" => "123456",
      "eposta" => "[email protected]",
      "kadi" => "Tayfun Erbilen",
));
if ( $insert ){
    $last_id = $db->lastInsertId();
    print "insert işlemi başarılı!";
}

Peki bunun ne farkı var?
diye soracak olursanız bu şekilde execute metodunda belirttiğimiz dizideki sıranın bir önemi kalmaz. İstediğiniz key değerini istediğiniz sırada yazabilirsiniz. Ayrıca key değerlerini mantıklı şekilde belirtirseniz anlama kolaylığıda sağlar.

UPDATE İşlemi

Update (güncelleme) işleminin insert’ten bir farkı yoktur aslında. Sadece insert into yerine update yazmalı ve bir where koşulu koymamız gerekiyor o kadar 🙂 Yinede biz ikisininde bir örneğini yapalım..

mysql_ li fonksiyonlarda update işlemi;

$update = mysql_query("UPDATE uyeler SET
uye_kadi = 'prototürk'
WHERE uye_kadi = 'Tayfun Erbilen'");
if ( $update ){
     print "güncelleme başarılı!";
}

PDO‘a update işlemi;

$query = $db->prepare("UPDATE uyeler SET
uye_kadi = :yeni_kadi
WHERE uye_kadi = :eski_kadi");
$update = $query->execute(array(
     "yeni_kadi" => "prototürk",
     "eski_kadi" => "Tayfun Erbilen"
));
if ( $update ){
     print "güncelleme başarılı!";
}

INSERT işleminde olduğu gibi burada da PDO güvenlik konusunda gerekeni yapmış oldu.

DELETE İşlemi (Toplu)

Toplu silme işlemlerinde mysql_li fonksiyonlar ve pdo ile birer örnek yapalım;

mysql_ li fonksiyonlarla silme işlemi;

$delete = mysql_query("DELETE FROM uyeler");

PDO da silme işlemi;

$delete = $db->exec("DELETE FROM uyeler");
print 'Toplam '.$delete.' üye silindi!';

DELETE İşlemi (Tek)

Sadece bir veriyi silmek için mysql_ li ve pdo’lu örneği yapalım. Elbette işin içine yine kullanıcıdan veri almak girince pdo daha güvenli bir işlem haline geliyor.

mysql_ li fonksiyonlarda tek veriyi silme işlemi;

$delete = mysql_query("DELETE FROM uyeler WHERE uye_id = {$_GET['id']}");

PDO da tek veriyi silme işlemi;

$query = $db->prepare("DELETE FROM uyeler WHERE uy_id = :id");
$delete = $query->execute(array(
   'id' => $_GET['id']
));

Veritabanı Bağlantısını Sonlandırma

İşimiz bitince mevcut bağlantıyı sonlandırmamız gerekir. Bunuda mysql_ li fonksiyonlarda ve pdo da nasıl yapabiliriz hemen görelim;

mysql_ li fonksiyonlarda bağlantı sonlandırma işlemi;

mysql_close($baglanti);

PDO da bağlantı sonlandırma işlemi;

$db = null;

Object Mapping Olayı

Bunun mysql_ li fonksiyonlarda olmadığına eminim. Varsa bile ben hiç denk gelmedim ama yok yok tamam 😀 PDO ‘da ise böyle bir güzellik var.. Peki bu object mapping tam olarak nedir? ne işe yarar? Bunu bir örnek ile anlatsam daha mantıklı sanırım..

<?php

class Uye {
   
   public function adsoyad(){
      return $this->uye_ad . ' ' . $this->uye_soyad;
   }

   public function rutbe(){
      if ( $this->uye_rutbe == 1 )
         return 'Yönetici';
      else
         return 'Üye';
   }

}

$query = $db->query("SELECT * FROM uyeler");
$query->setFetchMode(PDO::FETCH_CLASS, 'Uye');

foreach ( $query as $row ){
   print $row->adsoyad() . ': ' . $row->rutbe() . '<br />';
}

Evet gördüğünüz gibi üyeler tablosundan tüm üyeleri çektim. Ve Uye adında tanımlamış olduğum sınıfta bu bilgilere ulaşıp istediğim gibi kontroller yapabiliyorum. Daha sonra mevcut üyeleri foreach ile listelerken bu Uye sınıfındaki metodlara erişip istediklerimi kolayca kullanabiliyorum. Harika değil mi? Bence de öyle 🙂

Güvenlik

Veritabanı işlemlerinde SQL Injection diye illet bir şey var.. Yani SQL sorgularına müdahale etmek. Ve bu müdahale sonuçları çok kötü olabilir. Ancak korkmayın, PDO bu gibi kötü durumlar için koruyor..

Örneğin şöyle bir link yapımız olsun;
http://www.siteadi.com/delete.php?id=4

burada id parametresini kullanıcıdan alıyoruz.. Dolayısı ile bu değeri istediği gibi değiştirebilir. Şimdi bu id değerini alıp bir silme işlemi yapalım pdo ile.

$query = $db->prepare("DELETE FROM uyeler WHERE uye_id = :id");
$delete = $query->execute(array(
     "id" => $_GET['id']
));

Evet şuan silme işlemi yapıyor. Örneğin sql sorgusuna müdahale etmeyi deneyelim.. Mesela tüm üyeleri silmeye çalışalım;
http://www.siteadi.com/delete.php?id=’; DELETE FROM videolar; /*

Eğer bu şekilde bir işlem yapılsaydı ve pdo yerine mysql_ li fonksiyonlar kullanılmış olsaydık çoktan sql injection yemiş ve bütün üyelerimizi kaybetmiş olacaktır. Ancak pdo yukarıdaki kodlarda bunun kontrolünü yaptığı için hiçbir şey olmadı ve hala mutluyuz 🙂

Daha fazlası için;
http://php.net/pdo

Yayınlayan

Tayfun Erbilen

2009'dan beri web işleriyle uğraşan, aynı zamanda amatör müziklede ilgilenen sıradan birisi..

“PDO Kullanımı” üzerine 38 yorum

  1. Merhaba hocam;

    PDO kullanarak da mysql’e bağlanacağım sizce Mysqli mi kullanmak daha güvenli olur yoksa PDO mu?

  2. merhaba tayfun hocam mysql fonksiyonlari değişecek diye bu pdo ortaya çıktı diyorlar bu ne kadar doğru ayrıca bu pdo geçmelimiyiz ?
    prototurk acilmis tekrar sevindim artik kapanmasin 🙂

  3. Tayfun kardeşim etkilenen satırı nasıl buluyoruzuz..

    Bir sorgu yaptık ve varsa yoksa mantığı kuracağız. Onuda anlatırsan bu ders tam olacak gibi 🙂

  4. PDO da hata mesajları varsayılan olarak kapalı geliyor. Bu mesajları açmak için veritabanı bağlantısı yaptıktan sonra aşağıdaki kodu yazmak gerekiyormuş, bende yeni öğrendim test ettim, onayladım.

    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  5. mysqli ve pdo arasında gidip geliyordum hangisini öğrensem diye sayende soru işaretlerinden kurtuldum eline sağlık tayfun hoca çok sagol

  6. Pdo hakkında gerçekten iyi bilgiler, php.net üzerinde baktım anlamadım ama burada daha iyi anladım teşekkürler.

  7. Allah senden razı olsun,sayende php’yi ögrendim,hemde burada kolayca anlayacagımız formülleri veriyorsun.

  8. Anlatımlarınız Gerçekten Çok Güzel Bende PDO Sizin Sayenizde Geçtim ve Öğrendim Uzun Zamandır Geçmek İstiyordum Gerçekten Başarılı

  9. Hemşerim,

    Senden ilk elden anlaşılır ve şekilde anlattığın -özelikle php konusunda- bir çok şey öğrendim.
    Yüreğine sağlık.

  10. Sıfırdan PHP öğreniyorum ve başlamışken direk PDO’dan başlamak istedim. Emeğine sağlık, her şey basit ve apaçık ortada. İlk başta PHP’nin CRUD sistemini öğrenmek istedim, o yüzden kaynağın bana çok yardımcı oldu hakkını helal et. Şu an hepsini kolay bir şekilde yapabiliyorum. Benim gibi CRUD işlemlerini senin kaynağın ile yapacak arkadaşlar için ufak bir düzeltme yapmak istedim. Her yerde veritabanı bağlantısını “$db->query” olarak belirlemişsin fakat PDO tekil veri çekme işleminde “$pdo->query” olarak kalmış. Ben farklı bir dilden geçiş yaptığım için sorun olmadı gözüme çarptı düzelttim kendim denerken fakat sıfırdan kod öğrenmeye çalışanlar için sıkıntı yaratabilir. Tekrar tekrar emeğine sağlık, hoşçakal.

  11. Çok teşekkürler. Çok kullanışlı bir anlatım olmuş. İşime yarıyor.
    Biraz da jquery öğrenebilsem ve php ile birlikte çalıştırabilsem getti posttu ajaxtı. off tadından yenmeyecek… :/

  12. Merhaba Tayfun bey,

    PDO ile php versiyonlarının bağlantısı var mı? Bu makale ile öğrenmeye PDO başladım. PHP 7 ile mi başladı PDO?

    Teşekkürler.

  13. eğitim videolarınızı indirdim izlemeye başladım , sanırım pdo değil peki ben en baştan nasıl takip edecem pdo yu ?. eğitim seti yok mu izlesem?

  14. Çok yararlı bir konu olmuş hocam teşekkürler. Size bir sorum olacak bu konuda SELECT işlemini QUEERY methodu ile işlettiğinizi görüyorum. Bu SQL Injection’a yol açıyor diyorlar. QUERY methodu yerine PREPARE methodunu kullanın diyorlar. Bu doğru mu yani bir güvenlik açığı çıkar mı?

  15. $insert = $db->query(“insert into uyeler (uye_tamad,uye_sifre,uye_eposta) values(‘asd’,’33333′,’eposta’)”);
    if ( $insert ){
    $last_id = $db->lastInsertId();
    print “insert işlemi başarılı!”.$last_id;
    }

    Böyle yazınca Bir fark oluyor mu sizin insert işleminden farklı olarak sizin yazdığınız mı normalde olması gereken

  16. Bir sorum olucaktı diger forumlarda pdo araştırıyorumda bazıları query ile bazıları exec ile yapmış mesala siz hepsini prepare execute ile yapmışsınız bunların arasındaki fark nedir bunu öğrenebilirmiyim ?

  17. @okan beydanol, o şekilde de yapabilirsin insert işlemini sorun olmaz. Exec kullanmadım diğerini kullandım güvenlik açıkları oluşmasın diye. Bana kalırsa bu yol daha doğru olanıdır.

  18. ben de php ye yeni gecis yapanlardanim, özellikle Object Mapping olayi ile, php de veritabanina entity yaklasimi sunulabilecegini ilk sende gördüm, bu isleri gercekten cok kolaylastirir paylasimin icin cok tesekkürler Tayfun, ellerin dert görmesin:)
    bir de bize basit bir mvc uygulamasi ile object mapping i birlestiren bir calisma gösterebilir misin?

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir