PDO Prepare Kullanımı, Escape ve Avantajları

Nesne yönelimli olarak veritabanına bağlanabilme yöntemlerini önceki yazılarımızın birisinde anlatmıştık. Veritabanına SQL Injection’dan korunmak amacıyla yapabileceğimiz şeyler eski sistemlerde kısıtlıydı ve gereksiz fonksiyonlar kullanıyorduk. PDO kullanıyorsak bunun iki yolu var: quote ve prepare . Normal deyimler kullanıyorsak eğer PDO::quote kullanmamız daha mantıklı olacaktır. PDO::quote dediğimiz fonksiyon aslında karakterleri bir string verisine dönüştürmemizi sağlayan fonksiyonlardır. Escape etmeden yapılan sorgular güvenlik açıklarına sebep olabilir . Verimizin önüne “\” karakteri koyarak sorguda geçersiz sayılmasını sağlıyoruz.

PHP.Net’e bakarsak bununla ilgili şöyle bir örnek verdiğini görebiliriz:

$string = 'Münasebetsiz \' dizge';
Öncelenmemiş dizge: Münasebetsiz ' dizge
Öncelenmiş dizge: 'Münasebetsiz '' dizge'

Eğer bakarsak ‘Münasabetsiz \’ dizge’ bir adet kesme işareti var. Escape edilmemiş dizgede bu olduğu gibi çıkıyor. Gönderilen verinin string olduğunu bitirmiş oluyor. Yani o kesme işaretinden sonra herhangi bir SQL kodu yazılırsa çalışma ihtimali var.

Hazırlanmamış deyim kullanılıyorsa eğer yapabileceğiniz tek yöntem var: PDO::quote . Veritabanı  sorgusunda kullanacağımız deyim için şu şekilde bir kullanım sergileyebiliriz: Normal veriyi aynı mysql_real_escape_string gibi bir fonksiyon kullanırmışcasına ekleyeceğimiz string’e uyguluyoruz. Yani;

$r = new PDO('mysql:host=localhost;dbname=yeni','root','pass');

$string = 'Merhaba \' dünya!';

echo "Escape edilmemiş: $string\n";
echo "Escape edilmiş:" . $r->quote($string) . "\n";

Çıktılara bakarsak eğer kesme işaretinin normal bir karaktermiş gibi çıktığını göreceğiz.

Escape edilmemiş: Merhaba ' dünya!
Escape edilmiş: 'Merhaba '' dünya!'

Karakterler zararsız hale getirildi. Artık SQL sorgusuna etki etmeyecektir. Ama bakın burada PHP’nin bize ne dediğine?

Bu işlevi SQL deyimlerini oluştururken kullanıyorsanız, kullanıcı girdisini bir SQL deyimi haline getirmek için PDO::quote() yerine PDO::prepare() ile değiştirgeleri ilişkilendirilmiş SQL deyimleri hazırlamanızı hararetle öneririz. Değiştirgelerle ilişkilendirimiş hazır deyimler taşınabilir olmaktan başka daha kullanışlı ve SQL zerkine bağışık olmanın yanında sorgunun derlenmiş hali hem sunucuda hem de istemcide bulunduğundan yorumlanan sorgulardan çok daha hızlıdır.

PDO sürücülerinin hepsi bu yöntemi gerçeklemez. (özellikle PDO_ODBC) Bu bakımdan hazır deyimleri kullanmaya hazır olmalısınız.

Hazır deyimler, PDO’nun bize sağladığı en büyük avantajlardan biridir. Bu avantajların başında PDO::quote’ye göre daha hızlı olan PDO::prepare vardır. SQL sorgusu yer tutucularla yazılır ve prepare ile hazırlanır. Bu yer tutucular isimlendirilmiş veya isimlendirilmemiş olabilir. Yer tutucuların değerlerini dizilerle ayarlarız. 

Hazır deyimleri kullanmak oldukça basittir. 2 adet yer tutucu bulunmaktadır ve bu yer tutucular herhangi bir veri tipi için kullanılabilir. İsimsiz yer tutucu dediğimiz soru işaretleri sorgunun arasında kullanılır. Şu şekilde bir kullanımı vardır SQL deyiminde:

	$kayit_sql = "INSERT INTO $this->tablo ($this->username_sutun, $this->password_sutun, $this->email_sutun, $this->onayli_sutun) values (?,?,?,?)";
	$data = array(
	'kulturlupenguen',
	'sifrenin_hashlanmis_hali',
	'bilmemne@hotmail.com',
	'onayli' );  
	$kayit_sorgusu = $this->baglanti->prepare($kayit_sql);
	// Sorguyu çalıştır.
	$kayit_sorgusu->execute($data);

SQL sorgusunda dikkat ettiyseniz “?” işaretini tırnak içine almadan yazdık. Verilerimizi de $data adında bir dizi oluşturup yazdık. Ardından SQL kodunu hazırladık ( prepare($kayit_sql) ) . Ve execute ile verilerin olduğu diziyi çalıştırıdık. Sorgu veritabanına problemsiz gönderildi. Ve çok daha hızlı gönderildi diğer yöntemlere göre.

İsimli tutucular daha basit anlayabileceğimiz ve başka bir programcının da daha kolay okuyup anlaması için daha yararlı olacaktır. Onun dışında isimsiz yer tutuculardan fazla farkı yok. Onu da şu şekilde kullanabiliriz:

	$kayit_sql = "INSERT INTO $this->tablo ($this->username_sutun, $this->password_sutun, $this->email_sutun, $this->onayli_sutun) values (:nick, :pass, :email, :o nayli)";
	$data = array(
	'nick' => 'kulturlupenguen',
	'pass' => 'sifrenin_hashlanmis_hali',
	'email' => 'bilmemne@hotmail.com',
	'onayli' => 'onayli' );  
	$kayit_sorgusu = $this->baglanti->prepare($kayit_sql);
	// Sorguyu çalıştır.
	$kayit_sorgusu->execute($data);

İsimli tutucular kullanırken dikkat etmemiz gereken tek şey dizimizin anahtarlarının sorguda belirttiğimiz isimde olması. Anahtar dediğimiz şey bir verinin karşısına “=>” işareti çıkmasıdır. Benim tercihim ve önerim isimli tutucu kullanmanız olacaktır.

  • Başlı başına bir SQL Injection koruması sağlar.
  • Nesne yönelimli programlama yaparsınız ki diğer türlerden çok daha basittir.
  • Hazır deyimler kullanarak diğer korunma yöntemlerinden daha hızlı işlem yaparsınız. Bu büyük bir sistem kurmayı hedefleyen biriyseniz, ki büyük sistemlerde mikrosaniyelerin bile önemi vardır, kesinlikle kullanmanız gerekenlerden birisidir.
  • Çoklu sorgu yapıyorsanız PDO::query den daha hızlı olmanızı sağlar.
  • Sürücü sizin için SQL koruması yapar.

  • PHP 4 ile uyumlu değildir. (PHP 4′te OOP yok)
  • Yeni yeni OOP öğrenenler için zor olacaktır.

Eğer hala eski yöntemler kullanıyorsanız, belki değişim iyi gelebilir. Onun dışında performans da düşük ise bu yöntemi denemelisiniz.

Bir Cevap Yazın

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