- Konu sahibi
- #1
PHP prepare nedir?
PHP'de
prepare, SQL sorgusunu verilerden ayrı hazırlamayı sağlayan prepared statement yöntemidir. Sorgunun içine değişkenleri metin birleştirmeyle eklemek yerine ? veya :ad gibi yer tutucular kullanılır; gerçek değerler daha sonra execute() ile gönderilir. Bu yaklaşım SQL injection riskini azaltır, yer tutuculara ayrı değer bağlamayı sağlar ve aynı sorgunun farklı değerlerle tekrar kullanılmasını kolaylaştırır.PHP'de en yaygın kullanım PDO'daki
PDO::prepare() metodudur. mysqli kullanıyorsanız karşılığı mysqli_prepare() veya nesne yönelimli arayüzde $mysqli->prepare() metodudur. Aşağıdaki örnek PDO ile çalışır.PDO prepare nasıl çalışır?
Hazırlanan sorguda kullanıcıdan gelen veri SQL kodunun parçası olarak değil, parametre değeri olarak ele alınır. Örneğin kullanıcı adı için sorguyu şu şekilde birleştirmek hatalıdır:
Kod:
$sql = "SELECT id FROM users WHERE username = '$username'";
Doğru yaklaşım, sorguyu yer tutucuyla hazırlayıp değeri ayrı vermektir:
Kod:
$statement = $pdo->prepare(
'SELECT id FROM users WHERE username = :username'
);
$statement->execute(['username' => $username]);
Burada
:username bir değerin yerini tutar. Tablo adı, sütun adı veya SQL anahtar kelimesi için kullanılamaz. Örneğin ORDER BY :column sütun adını bağlamaz; sorgu kabul edilse bile beklenen sütuna göre sıralama sağlamaz; dinamik sütun seçimi gerekiyorsa izin verilen sütunları sabit bir listeyle eşleştirmek gerekir.Çalışan en küçük örnek
Bu örnek veritabanı sunucusu gerektirmeyen, bellekte çalışan SQLite bağlantısı kullanır. Ön koşul, PHP kurulumunda PDO SQLite sürücüsünün etkin olmasıdır.
- Aşağıdaki kodu
prepare.phpadıyla kaydedin. - Komut satırında
php prepare.phpkomutunu çalıştırın. - Ekrandaki sonucu, sorgunun parametreyle başarıyla çalıştığını doğrulamak için kontrol edin.
Kod:
<?php
declare(strict_types=1);
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec(
'CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
email TEXT NOT NULL
)'
);
$insert = $pdo->prepare(
'INSERT INTO users (username, email) VALUES (:username, :email)'
);
$insert->execute([
'username' => 'ayse',
'email' => '[email protected]',
]);
$username = 'ayse';
$select = $pdo->prepare(
'SELECT id, username, email FROM users WHERE username = :username'
);
$select->execute(['username' => $username]);
$user = $select->fetch(PDO::FETCH_ASSOC);
if ($user === false) {
echo "Kullanıcı bulunamadı\n";
exit;
}
echo $user['username'] . ' - ' . $user['email'] . "\n";
Beklenen başarı çıktısı şudur:
Kod:
ayse - [email protected]
Bu çıktı alınmıyorsa önce PDO SQLite sürücüsünün etkin olup olmadığını ve dosyanın PHP CLI ile çalıştırıldığını kontrol edin.
PDOException oluşursa hata mesajı bağlantı, SQL sözdizimi veya tablo oluşturma aşamalarından hangisinin başarısız olduğunu gösterir. MySQL veya PostgreSQL’de de prepare() ve execute() modeli kullanılır; ancak DSN yanında SQL sözdizimi, sürücü seçenekleri ve tür davranışları da kontrol edilmelidir. PDO, farklı veritabanlarının SQL dilini otomatik dönüştürmez.PDO mu, mysqli mi?
Her iki yöntem de parametreli sorgu çalıştırabilir. Kullandığınız veritabanı ve projenin mevcut bağlantı katmanı, seçimdeki temel ölçüttür.
| Özellik | PDO | MySQLi |
|---|---|---|
| Veritabanı desteği | Birden fazla sürücüyle kullanılabilir | MySQL ve MariaDB odaklıdır |
| Yer tutucu türü | İsimli veya soru işaretli | Soru işaretli |
| Tip bağlama | Gerekirse bindValue() veya bindParam() | Genellikle bind_param() ile açık tip belirtilir |
| Uygun tercih | Taşınabilir veya yeni PDO tabanlı uygulamalar | Yalnızca MySQL uyumlu mevcut projeler |
PDO’da hata modu sürüme göre değişebileceğinden örnekte açıkça
PDO::ERRMODE_EXCEPTION ayarlanır; başarısız sorguların istisna olarak ele alınmasını sağlar. Üretim kodunda bağlantı bilgilerini kaynak dosyaya sabitlemek yerine uygulamanın yapılandırma mekanizmasından okuyun.Sık yapılan hatalar
- Değeri sorgu metnine birleştirmek:
prepare()çağrılmış olsa bile kullanıcı girdisini ayrıca SQL metnine eklemek korumayı bozar. - Yer tutucuyu tırnak içine almak:
WHERE username = ':username'ifadesi parametre olarak değil, sabit metin olarak değerlendirilir. DoğrusuWHERE username = :usernamebiçimidir. - Parametre ile sütun adını değiştirmeye çalışmak: Yer tutucular yalnızca değerler içindir. Sütun adı gerekiyorsa sabit izin listesi kullanın.
- Sonuç yokken doğrudan dizi okumak:
fetch()sonucufalseolabilir; kullanmadan önce bu durumu kontrol edin. - Tekrarlanan sorgularda yanlış beklenti kurmak:
prepare()güvenliği ve parametre yönetimini sağlar; her veritabanında otomatik olarak ölçülebilir performans artışı garanti etmez.
Sık sorulan sorular
prepare ile sorguyu yalnızca bir kez hazırlamak zorunda mıyım?
Hayır. Bir
PDOStatement nesnesini farklı değerlerle tekrar execute() edebilirsiniz. Aynı işlem döngü içinde çok kez yapılacaksa bu kullanım, sorgu metnini her seferinde yeniden kurmaktan daha düzenlidir.bindValue ile bindParam arasındaki temel fark nedir?
bindValue() çağrıldığı andaki değeri bağlar. bindParam() ise bir değişkene referans bağlar ve sorgu çalıştırıldığında o değişkenin güncel değerini kullanır. Değişkeni sonradan değiştirmeyecekseniz execute() dizisi veya bindValue() genellikle daha anlaşılırdır.