PHP Data Objects (PDO)
Artık “mysql_connect“, “mysql_query” fonksiyonlarının müfredattan kalkma zamanı geliyor, PHP’de kendi resmi dökümantasyonunda da bunun sinyalini vermeye başlamış; “mysql” fonksiyonlarının sayfasında aşağıdaki gibi bir öneriyle karşılaşıyoruz;
This extension is not recommended for writing new code. Instead, either the mysqli or PDO_MySQL extension should be used. See also the MySQL API Overview for further help while choosing a MySQL API.
Özetle artık bunları kullanmanızı önermiyoruz, PDO ya da MySQLi‘ye geçin diyor. Peki nedir bunlar? Şuradaki karşılaştırmaya baktığımızda MySQLi ile PDO arasında çok fark olmadığını görebilirsiniz.
PDO’da çoğu veritabanı sürücüsü kullanılmasına olanak sağlayan, MySQLi ise sadece MySQL destekleyen ve PDO’ya göre biraz daha karmaşık ve kapsamlı bir arayüz diyebiliriz. Sonuç olarak ikisi de öneriliyor. Ben burada PDO’dan bahsetmeye çalışacağım, iksinden birisinin kullanım şeklini kavradığınızda diğerini de rahatlıkla kullana bileceğinize inanıyorum.
PDO nedir?
PDO(PHP Data Objects / PHP Veri Objeleri) özetle; hafif ve tutarlı bir şekilde veritabanına erişimi sağlayan bir arayüz. Adından da anlayacağınız üzerie “Object Oriented Programming” arayüzüne sahip, onlarca veritabanı sürücüsü destekliyor;
- Cubrid
- FreeTDS / Microsoft SQL Server / Sybase
- Firebird/Interbase 6
- IBM DB2
- IBM Informix Dynamic Server
- MySQL 3.x/4.x/5.x
- Oracle Call Interface
- ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
- PostgreSQL
- SQLite 3 and SQLite 2
- Microsoft SQL Server / SQL Azure
İleride daha farklı bir veritabanı sürücüsüne geçmek istediğinizde sisteminizi temelli olarak değiştirmek yerine PDO ile kaldığınız yerden bir takım ufak modifikasyonlar ile bu işi gerçekleştirebilirsiniz.
Bunların haricinde PDO 5.1‘den itibaren geliyor, yani çalışabilmesi için güncel versiyonlara ihtiyacınız olacak.
PDO ile MYSQL’e bağlanmak
Genel olarak bağlantı olaylarını bir PDO sınıfını tanımlarken bir DSN yani “Data Source Name” ile belirtiyoruz. Hangi veritabanı sürücüsüne bağlanacağımızı ve bilgilerimizi DSN ile ifade ediyoruz. Diğer iki parametrede ise veritabanı kullanıcı adı ve şifremizi giriyoruz.
$db = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
Diğer sürücülerin DSN ifadeleri için şuraya bakın.
$dsn = 'mysql:host=localhost;dbname=test'; $user = 'dbuser'; $password = 'mypassword'; try { $db = new PDO($dsn, $user, $password); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); }
Bu şekilde de bağlantı hatalarını yakalıyoruz.
Sorgu hatalarını yönetmek
Query ya da exec gibi sorgu gönderdiğimiz metodlar eğer sorguyu gerçekleştirdiklerinde bir hata ile karşılaşırlarsa false dönerler. Başarısız gerçekleşen bu sorguların hata mesajlarına ulaşmak için errorInfo metodunu kullanacağız.
Bu metod bize son yaptığımız sorgudaki hatanın kodunu ve mesajını içeren bir array döndürür. 3 adet elemanı bulunan bu dizide 0. ve 1. eleman hata kodlarını, 2. eleman ise hata mesajını verir.
if($users = $db->query('SELECT * FROM users WHERE')) { // Sorgu başarıyla çalışırsa üyeleri listeleriz } else { echo 'Sorguda bir hata meydana geldi.'; $error = $db->errorInfo(); echo 'Hata mesajı: ' . $error[2]; }
Örnekteki sorguda WHERE dedikten sonra herhangi bir koşul belirtmediğimiz için hata verecektir ve ekrana ilgili hatanın mesajı yazacaktır.
PDO ile sorgu göndermek
Eğer yapacağımız sorgudan bir sonuç almayı beklemiyorsak “exec“, bir sonuç isteniyorsa “query” metodlarını kullanmalıyız. Özetle; “DELETE/UPDATE/INSERT” gibi sorgularımız için “exec”, “SELECT” gibi sorgularımız için “query”.
try { $db = new PDO('mysql:host=localhost;dbname=test', $user, $password); $db->exec('SET NAMES `UTF-8`'); $count = $db->exec('DELETE FROM messages WHERE old = 1'); echo $count . ' messages deleted'; } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); }
Exec metodu sonuç olarak etki ettiği satır sayısını döndürür.
Değişkenleri sorgulara dahil etmek
PDO’nun en önemli özelliklerinden birisi olan binding yöntemi sayesinde hazırladığımız sorgulara değişkenlerimizi güvenli ve düzgün bir şekilde yerleştirebiliyoruz.
Bunun için önce prepare metodu ile sorgumuzu hazırlayıp dışarıdan değerler vereceğimiz yerlere “?” (soru işareti) yerleştiriyoruz. Sonrasında hazırladığımızı sorguya execute metodu ile soru işareti olan yerlere gelecek değerlerimizi gönderiyoruz.
// Sorgumuzu hazırlıyoruz $query = $db->prepare('INSERT INTO users (name, email) VALUES(?, ?)'); // Sorguda belirttiğimiz yerlere gelecek değerleri veriyoruz $query->execute(array('Musa', '[email protected]'));
Bu ifadeyi çalıştırdığımızda çalıştırılacak sorgu aşağıdaki gibi olacaktır;
INSERT INTO users (name, email) VALUES('Musa', '[email protected]')
PDO kullanırken tüm dışarıdan aldığımız değişkenleri sorgularımıza bu yöntem ile dahil etmemiz uygulamamızın güvenliği ve düzeni açısından çok önemlidir. Bu yöntem sayesinde SQL injection açıklarından da arınmış oluyoruz.
PDO ile verileri listelemek
Bunun için yukarıda bahsettiğim query metodunu kullanacağız.
foreach($db->query('SELECT * FROM users') as $row) { echo $row['name'] . '<br/>'; }
PDO ile bir satır veri çekmek
Bunun için query ile sorgumuzu çağırdıktan sonra fetch ile ilk sonucu alacağız.
$row = $db->query('SELECT * FROM users WHERE id = 1')->fetch(); echo $row['name'];
Yeni bir kayıt eklemek
Yeni bir kayıt eklemek için exec metodunu kullanacağız. Sonrasında eğer eklediğimiz satırın ID’sini almak istiyorsak lastInsertId metodunu çağıracağız. Eklerken bir sorun gerçekleşirse exec metodu false dönecektir. Bu nedenle öncelikle eklenip eklenmediği kontrol edip sonrasında ID’yi ekrana yazdırabiliriz.
if($db->exec('INSERT INTO users (name) VALUES ("Musa")')) { $id = $db->lastInsertId(); echo 'Yeni eklenen üyenin IDsi: ' . $id; } else { echo 'Yeni kayıt eklerken bir hata meydana geldi.'; }
Sorguları geri alabilme
PDO’nun bir diğer önemli özelliği ise transaction denilen ifade edilen sorguları istenildiğinde geri alabilme ya da uygulayabilmesidir.
Yukarıdaki sorgu ifadelerini kullanmadan önce beginTransaction metodunu çağırarak geri alma işlemi yapabileceğimiz sorguları yazmaya başladığımızı ifade etmemiz gerekiyor.
BeginTransaction metodunu çalıştırdıktan sonra yazacağımız tüm ekleme, düzenleme ve silme sorguları normal kullandığımız şekilde çalışmaya devam eder. Eğer sorgular devam ederken tüm bu aralıktaki sorguları geri almak istersek rollBack metodunu çağırırız. Bu metodu çalıştırdığımızda beginTransaction’dan rollBack metoduna kadar yazdığımız tüm ekleme, düzenleme ve silme sorguları geri alınır.
Bu ifadeleri kullanırken bilmeniz gereken önemli bir konu; DROP TABLE ya da CREATE TABLE gibi tabloları komple silen ya da yeni tablolar ekleyen sorgular geri alınamaz. Fakat DELETE sorgusu ile sildiğiniz ya da UPDATE ile düzenlediğiniz her sorguyu geri alabilirsiniz.
// İşlemleri başlattığımızı ifade ediyoruz $db->beginTransaction(); $db->exec('INSERT INTO users (name) VALUES ("Ahmet")'); $db->exec('UPDATE users SET name = "Ali"'); $db->exec('DELETE FROM users WHERE name = "Hasan"'); // Yaptığımız sorguları geri aldık $db->rollBack();
Yaptığımız sorguları geri almak yerine başarıyla sonuçlandığında gerçekten uygulamak istiyorsak commit metodunu çağırırız.
PDO bağlantısını kapatmak
Eski MySQL bağlantısında da olduğu gibi açtığınız bağlantıyı kapatmasanız da PHP otomatik olarak işlem sonunda bağlantıyı keser. Fakat ille de ben kapatacağım diyorsanız “null” tanımlamanız yeterli.
// bağlantıyı açtık $db = new PDO('mysql:host=localhost;dbname=test', $user, $pass);[ // bağlantıyı kapattık $db = null;
Dahası …
Ben bu yazıda PDO’nun temel ihtiyaç duyulan ifadelerinden bahsetmeye çalıştım. Fakat bununla yetinmeyip PDO hakkında daha fazla bilgi edinmek için şuralardaki örnekleri ve açıklamaları incelemeye devam edin.
Bir sonraki serüvende görüşmek üzere, hoşçakalın.
Yazılanlar ilgini çektiyse, yenilerinden haberdar olmak için e-mail bültenine abone olabilirsin.
Piyasada kaliteli geliştiricilerin çoğalması adına daha çok Türkçe içeriğe ihtiyaç var. Bu anlamda kaynak olabilecek nitelikte başarılı bir yazı olmuş. Elinize sağlık.
Hocam temiz ve güzel bir anlatım. Teşekkür ederim. PDO konusunda ki diğer anlatımlarınızı da bekliyorum.
Hocam sormak istediğim bir konuda,
PDO ile veri listelerken
Burada fetch(); i kullanmışınız. Ben bu fetch(); değerini hangisini tanımladığınızı anlayamadım.
Yani normalde mysql_fetch_object, array, row, assoac gibi tanımlar var. Burada derleyici fetch(); değerini belirttiğinizde hangisini okuyarak işlem yapıyor.
sorunuz üzerine PHP class (sınıf) yapısı yazısında “Metod zincirleme” başlığı altında bu durumu açıkladım.
burada bir önceki metodda query ile çağırılan sorguyu fetch ediyor.
fetch parametresinde bunu belirtmelisiniz. örneğin
fetch(PDO::FETCH_ASSOC) büyük harfle. eğer boş bırakırsanız karışık gelir değerler yani hem sayı ile hemde tablo ismi ile listeler. Reklam olmasın ama burada detaylı bir makale yazmıştım bir ara: http://makaleci.com/pdo-ve-mysql-islemleri-baslangic-ve-orta-duzey-ekleme-silme-guncelleme-listeleme-baglanma.html
Çok güzel konular, anlatım ve kodlama yapınız da gayet temiz. İleri seviye daha çok konu bekliyoruz 🙂
Emeğinize sağlık..
Salam. Gozel dersliklerdi. Yeri gelmiwken. AZERBAYCANDAN SIZE SALAMLAR
Tesekkrler
hocam ben anlamadım bunu.mysql connectden vs ne farkı var ki şimdi.bence yazının sözel kısmını uzatmalısınız
PDO’nun “mysql_connect” gibi ifadelerden farkı çok. Ama özetlememi istersen; yeni, daha kullanışlı, güvenilir ve fonksiyonel diyebiliriz. Daha iyi anlamak için mutlaka en yakın projenizde denemenizi öneririm.
PDO veritabanı işlemleri için mysql_ gibi fonksiyonlardan çok daha güvenli ve hızlıdır. Ama gel de anlat bunu. Millet kullanmak istemiyor, kullanınca garip bakıyorlar.
Hazırlanmış deyimleri de yazsaydınız keşke, SQL Injection’dan korunmak için bir numaralı PDO yöntemi.
Teşekkürler, umarım PHP geliştiricilerinin çoğu PDO kullanmaya başlar.
Merhaba, öncelikle yeni php öğrenen biri olarak şu anda kendi blog scriptimi yazıyorum veritabanları ile ilgili bir araştırma yaparken pdo işlemlerini gördüm. Sormak istediğim ise, mysql_ komutlarını öğrenmek yerine pdo komutlarını öğrensem sizce daha mı mantıklı olur madem mysql_ komutları kalkacak yakında öğrenmemin ne anlamı olur değil mi ? sizin düşünceniz nedir ?
elbette pdo öğrenmenizi tavsiye ederim
pdo php 5.1’in üstü versiyonlarda gömülü olarakmı geliyor yoksa ayrı kurulum yapmak gereklimi?
aynen dediğiniz gibi, 5.1 ve üzerinde varsayılan olarak var.
db fonksiyonlarımı pdo’ya çevirdim. mysql fonksiyonlarına göre daha basit ve kullanışlı. sonuca giderken fazla dolanmıyosunuz 🙂
umarım PHP geliştiricilerinin çoğu PDO kullanmaya başlar.
eline sağlık çok güzel anlatım. Faydalı bir sunum oldu teşekkürler
İleri Seviyede başka derslerde olsaydı güzel olurdu
Güzel döküman ellerinize saglık
performans bakımından özelliklede anlık mesajlaşma sistemi tarzı uygulamalarda pdo mu yoksa mysqli mi daha performanslı olur
Təşəkkürlər. Faydalı məqalədir.
eChO “HELAL BE”;
Hocam bilgiler çok yararlı ve çok sade anlatılmış şekilde gerçekten bunun için büyük bir teşekkürü kesinlikle hak ediyorsunuz. Benim sizden bir de ricam olacak. Kafamda bir fikir var yalnız bunu koda dökerken bir yerde tıkandım eğer benimle email üzerinden iletişime geçip yardımcı olursanız çok sevinirim.
evet kendimizi geliştirmemiz gerekiyor. demekki kodu bir kere yazıp yuz yere kopyalamak pek kendini geliştirmek olmuyor teşekkür ederim.
Çox faydalı məqalədir.
Bilgi için çok teşekkürler.
Makale için teşekkürler 🙂
öncelikle verdiğiniz bilgiler için teşekkürler.
ben ilk defa web sitesinde veri tabanı kullanmaya çalışıyorum ve sürekli
SQLSTATE[HY000] [1045] Access denied for user ‘cupsamet_samet1’@’lineko72.isimtescil.net’ (using password: YES)
böyle bir hata alıyorum
kulanıcı adını ve şifreyi doğru girdiğime eminim
try {
$db = new PDO(“mysql:host=93.89.225.106;dbname=cupsamet_deneme”, “cupsamet_samet1”, “pass”);
} catch ( PDOException $e ){
print $e->getMessage();
}
site bu
yardımcı olursanız sevinirim.
Paylaşım için Teşekkürler
PHP msql sınıfına olan desteğini ileride tamamen bitireceğini açıkladı. mysqli veya PDO kullanılmasını öneriyor. Wamp son sürümünü kurarsanız ve hataları gösteri seçtiyseniz mysql komutları bulunan php sayfası çalıştığında bu uyarıyı browserda görebilirsiniz.
Hocam çok güzel anlatmışsınız ağzınıza sağlık.. Sadece birşey anladımadım exec methodu… query den farkı ne? Biraz detay verebilirmisiniz…
Təşəkkürler. Size bi sorucam burda
$count = current($db->query(“select count(*) from table where login=’.$login.'”)->fetch());
echo “$count”;
burda neden logini $login deyiskenine beraber olan sqllarin toplam cemini vermiyor ? Eger mumkunse cevaplandirardiz.
hocam suan kod hata vermiyor ama sitede göstermiyorda su şekilde cağiriyorum ama cağirmiyor
bir ilgilenirsen sevinirim
şeklinde deneyebilir misin?
bu sayfada daha önce pdo ile güncelleme işlemi anlatılıyordu, kendim ve öğrencilerim bu kısımdan epey faydalanıyorlardı, sayfaya güncelleme kısmını tekrar ekler misiniz lütfen..
Ayrıca sitenizdeki kısa ve öz anlatım da gayet başarılı..
PDO MySQL veritabanı sınıfından bahsediyor olabilir misiniz?
http://www.phpr.org/pdo-mysql-veritabani-sinifi/
foreach($db->query(‘SELECT * FROM isimler’) as $row) {
echo $row[‘name’] . ”;
bu sadece “name” sütununu gösteriyor daha fazla sütunu görüntülemek için ne yazmamız gerek?
[‘name’].[‘2.sutun]
veya [‘1.sutun’ . ‘2.sutun’] tarzı denedim hiç biri işe yaramadı
foreach($db->query(‘SELECT * FROM isimler’) as $row) {
echo $row[‘name’];
echo $row[‘2_sutun’];
}
şeklinde gerçekleşiyor.
Çok güzel anlatmışsınız.
Farkettiğim bir hata: “Değişkenleri sorgulara dahil etmek” bölümünde [email protected] ‘dan sonra tek tırnak eksik.
Yazım diliniz gayet açıklayıcı, Teşekkür ederim.
Dikkatiniz için tebrikler, bildirdiğiniz için teşekkürler, eksik tırnağı ekledim.
allah razı olsun sayenizde kimseye minnet duymadan 1-2 bişey öğreniyoruz
pdo konusunda güzel yazınızdan dolayı teşekkürler
Select ile Sql Injection açığı yemeyecek şekilde kullanıcıdan aldığım veriyi “where” ile kontrol ettikten sonra o veri ile ilgili veritabanından bazı bilgileri çekip ekranda göstermek istiyorum.(örn: Kullanıcının tıkladığı yazının idsini alıp veritabanındaki id ile eşleştirip, o id ile iligli içerik,resim,yazıbaşlığı gibi yerleri çekip ekrana yazdırmak-tabi bunları yaparken sql ınjection açığını yemeden) Sizce bunu nasıl yapabilriim?
Verdiğiniz select örneklerini inceledim ama birinde sql ınjection açığı var diğerindede açık yok ama onda da veri çekmiyorsunuz.
Yardımcı olurmusunuz?
Millet mysql güvenlik ve verimli kullanımı üzerine konuşadursun biz halen eski usül mysql bağlantı kuralım..
Faydalı bir konu.. Aslında direkt pdo verilse diğer mysql bağlantı yazıları buraya yönlendirilse daha iyi olacağı inancındayım.
2019 anywere?
$id = $db->lastInsertId();
echo $id;
4 dönmesi lazımken 0 dönüyor. veri tabanımda 0 ve 1 döndüren sütunum var ama onun da son değeri 0 değil 1. yani ne 4 dönüyor ne 1 dönüyor acil yardım nasıl son id yi alabilirim?