PHP PDO kullanımı

Öncelikle PHP PDO'nun ne olduğunu ve ne amaçla kullanıldığını görelim. PHP PDO(PHP Data Objects), PHP dilinde yazılı olan projenizin veritabanlarına erişmek için kullandığı basit bir kütüphanedir. PHP'de veritabanları üzerinde erişim sağlamak için data erişim katmanı oluşturur. En önemli özelliği, Mongo, Mysql, PostgreSQL vb. farklı veritabanlarına aynı kodlama ile sorunsuz bağlantı imkanı sağlamasıdır. Yani projeniz hangi veritabanını kullanırsa kullansın eğer PDO kütüphanesi ile kodladıysanız ekstradan herhangi bir düzenleme yapmanıza gerek kalmayacaktır.

PDO, PHP ile veritabanı arasında bir bağlantıyı temsil eder. PDOStatement ise herhangi bir sorguyu çalıştırdıktan sonra dönen sonuç kümesini temsil eder. PDOException, PDO tarafından oluşturulan hatayı temsil eder.

MySQL veritabanı

Bu makalemizde yapılacak örneği MySQL veritabanı kullanarak gerçekleştireceğiz. Örnek olarak ülkelerin tutulduğu bir tablo oluşturalım. Bu tablo içerisine de o ülkelere ait popülasyon bilgilerini örnek olarak girelim.

DROP TABLE IF EXISTS ulkeler;
CREATE TABLE ulkeler(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    ad VARCHAR(255), populasyon INT);

INSERT INTO ulkeler(ad, populasyon) VALUES('China', 1382050000);
INSERT INTO ulkeler(ad, populasyon) VALUES('India', 1313210000);
INSERT INTO ulkeler(ad, populasyon) VALUES('USA', 324666000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Indonesia', 260581000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Brazil', 207221000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Pakistan', 196626000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Nigeria', 186988000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Bangladesh', 162099000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Nigeria', 186988000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Russia', 146838000);
INSERT INTO ulkeler(ad, populasyon) VALUES('Japan', 126830000);

Bu komutla birlikte ulkeler adında bir tablo oluşturup içerisine veriler eklendi.

PHP Pdo Sorgusu

PDO da yaygın olarak kullanılan query() metodu ile veritabanına direkt sorgu atılmakta ve tekil sonuç dönmektedir. Dönen sonuca ulaşmak için fetch() metodu kullanılmaktadır.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$stm = $pdo->query("SELECT VERSION()");

$version = $stm->fetch();

echo $version[0] . PHP_EOL;
?>

Yukarıdaki örnek sorgu ile veritabanına ait versiyon bilgisi çekilmektedir. Örnek sorguda ilk satırda tanımlanan $dsn bilgisi hangi veritabanına bağlanılacağına yönelik bilgi içermektedir.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";

Sorguda göründüğü üzere localhost üzerinde çalışan mysql veritabanına bağlanılacak. Bağlantılacak veritabanının ismini de veritabanım olarak belirledik. Daha sonrasında username ve password bilgileri alttaki satırlarda girilmektedir. Sonuç olarak aşağıdaki şekilde bir sorgu sonucu ile karşılaşmaktayız.

5.7.22-0ubuntu0.16.04.1

PHP Pdo exec

PDO da önemli bir yere sahip olan exec() metodu, yapılan sorgulama sonucu etkilenen sorgu sayısını geri dönmektedir.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$nrows = $pdo->exec("DELETE FROM ulkeler WHERE id IN (1, 2, 3)");

echo "Etkilenen kayıt sayısı: $nrows";
?>

Yapılan sorgulama ile ulkeler tablosundan 1,2,3 idlerine sahip kayıtların silinmesi sağlamaktadır. Sonuç olarak ise örneğin üç kayıt silindiği için Etkilenen kayıt sayısı: 3 gibi bir sonuç dönecektir.

PHP Pdo fetch

PDO yapısında PDO::FETCH_ASSOC, PDO::FETCH_NUM ve PDO::FETCH_BOTH şeklinde üç farklı fetch kurgusu bulunmaktadır. PDO::FETCH_BOTH default olarak tanımlı olan tanımlamadır. PDO::FETCH_ASSOC tanımında, dönen dizin elemanının sütün adına göre dönmesi sağlanmaktadır. PDO::FETCH_NUM tanımında, dönen dizin elemanı ise sütun numarasına göre dönecek şekilde ayarlanmaktadır.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$stm = $pdo->query("SELECT * FROM ulkeler");

$rows = $stm->fetchAll(PDO::FETCH_NUM);

foreach($rows as $row) {

    printf("$row[0] $row[1] $row[2]\n");
}

?>

Yapılan sorgulamada dikkat ederseniz veriler $row[0], $row[1] ve $row[2] olarak çekilmektedir ve dönen içerikte veritabanından id, ad, populasyon alanlarına ait veriler listelenecektir.

Aşağıdaki sorguda ise direkt veritabanında kayıtlı olan sütun ismine göre verilerin çekilmesi sağlanmaktadır. Bunun için PDO::FETCH_ASSOC metodunu kullanmaktayız.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$stm = $pdo->query("SELECT * FROM ulkeler");

$rows = $stm->fetchAll(PDO::FETCH_ASSOC);

foreach($rows as $row) {

    printf("$row['id'] $row['ad'] $row['populasyon']\n");
}

?>

PHP PDO Parametre İlişkilendirmesi

SQL sorguları genellikle dinamik olarak oluşturulur. Sorgulamada setlenecek olan parametreler kullanıcı tarafından belirlenir. Ancak burada en önemli konu setlenilecek olan parametreleri bindValue() ve bindParam() gibi metodlar üzerinden gerçekleştirmeniz. Çünkü veritabanına bağlantıların gerçekleştirildiği kurgularda güvenlik en sorunlu olan kısımdır. Parametrik olan sorgular çoğunlukla veritabanına SQL injection gerçekleştirilmesi gibi sorunlara sebep olabilmektedir.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$id = 5;

$stm = $pdo->prepare("SELECT * FROM ulkeler WHERE id = ?");

$stm->bindValue(1, $id);
$stm->execute();

$row = $stm->fetch(PDO::FETCH_ASSOC);

echo "Id: " . $row['id'] . PHP_EOL;
echo "Ad: " . $row['ad'] . PHP_EOL;
echo "Popülasyon: " . $row['populasyon'] . PHP_EOL;

?>

Bu sorgu ile idsi 5 olan kaydın çıktısı dönecektir. Aşağıda ekranda görüntülenecek olan veri şu şekilde olacaktır;

Id: 5
Ad: Brazil
Popülasyon: 207221000

Aynı sorguyu bindParam() metodu ile gerçekleştirelim. Burada yapılacak sorgulamaya göre numerik olarak tanımlama yerine key- value olarak tanımlama gerçekleştirilmektedir.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$id = 5;

$stm = $pdo->prepare("SELECT * FROM ulkeler WHERE id = :id");
$stm->bindParam(":id", $id, PDO::PARAM_INT);
$stm->execute();

$row = $stm->fetch(PDO::FETCH_ASSOC);

echo "Id: " . $row['id'] . PHP_EOL;
echo "Ad: " . $row['ad'] . PHP_EOL;
echo "Popülasyon: " . $row['populasyon'] . PHP_EOL;

?>

Dikkat ederseniz artık id olarak tanımlama yapılıp, parametrelerde id'ye göre setlemeler gerçekleştirilmektedir. Aslında bu yöntem bindValue metodundan daha kullanışlı ve güvenilirdir. Tavsiyemiz kodlamalarınızda bunu kullanmanızdır. Zaten sonuç olarak elde edilecek ekran görüntüsü yukarıda görüntülenen çıktıdan farklı olmayacaktır.

PHP PDO lastInsertId() metodu

lastInsertId() metodu bizlere veritabanına eklenen herhangi bir veri olduğu zaman eklenen verinin rowId bilgisini dönmektedir. Bu veri çoğu zaman projemizde ilişkili veritabanını kurgusunu ayarlamada kullanılmaktadır. En güzel yani tekrardan select ile veritabanına sorgu atmamıza gerek kalmamakta, performans olarak baya etkin bir sonuç sunmaktadır.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

$pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Japan',  81050000)");
$pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Mexico', 550000)");
$pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Tunis',  938050000)");
$pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Benin',  182050000)");

$rowId = $pdo->lastInsertId();

echo "Son eklenen row id: $rowId\n";

?>

Gördüğünüz gibi yapılan sorgulama ile birlikte ulkeler veritabanına 4 ayrı kayıt ekledik. Bu kayıtlarında eklenmesinin ardından kayda ait id numarası ekrana aşağıdaki şekilde gelecektir.

Son eklenen row id: 12

PHP PDO Transactionlar

Transaction tanım olarak veritabanı işlemlerinde gerçekleştirilen unique birimdir. Özellikle birden fazla bağlantılı olan global projelerde bu kullanım önemli bir yer tutmaktadır. Çünkü yapılacak olan işlemler commit ve rollback isimli metodlarla desteklenmekte ve yapılan işlemlerin tümünün gerçekleştirilmesi garanti hale getirilmektedir.

<?php

$dsn = "mysql:host=localhost;dbname=veritabanim";
$user = "kullanici";
$passwd = "abc123";

$pdo = new PDO($dsn, $user, $passwd);

try {

    $pdo->beginTransaction();
    $pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Japan',  81050000)");
    $pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Mexico', 550000)");
    $pdo->exec("INSERT INTO ulkeler(ad, populasyon) VALUES('Tunis',  938050000)");
    $pdo->commit();

} catch(Exception $e) {
    $pdo->rollback();
    throw $e;
}
 
?>

Bu örnekte gördüğünüz gibi ulkeler veritabanına 3 yeni kayıt eklemeye çalışıyoruz. Öncelikle beginTransaction() metodu ile birlikte yeni bir transaction oluşturulması sağlandı. Yazılan kodlamada ya hep ya hiç kurgusuna göre kodumuz çalışacaktır. Yani çalıştırılan sorguda herhangi bir yerde sorun ortaya çıkarsa rollback ile geri dönecek ve kayıtlar veritabanına kayıt edilmeyecektir.

comments powered by Disqus