Tindakan terbaik untuk Anda akan tergantung pada bagaimana Anda mendekati akses data Anda. Ada tiga pendekatan yang dapat Anda ambil:
- Gunakan prosedur tersimpan
- Simpan kueri dalam kode (tetapi masukkan semua kueri Anda ke dalam fungsi dan perbaiki semuanya untuk menggunakan PDO sebagai parameter, seperti yang disebutkan sebelumnya)
- Gunakan alat ORM
Jika Anda ingin meneruskan SQL mentah Anda sendiri ke mesin database, maka prosedur tersimpan akan menjadi cara yang harus dilakukan jika semua yang ingin Anda lakukan adalah mengeluarkan SQL mentah dari kode PHP Anda tetapi tetap relatif tidak berubah. Prosedur tersimpan vs debat SQL mentah adalah sedikit perang suci, tetapi K. Scott Allen membuat poin yang sangat baik - meskipun yang sekali pakai - dalam sebuah artikel tentang basis data versi :
Saya cenderung condong ke arah tidak menggunakan prosedur tersimpan. Saya telah mengerjakan proyek di mana DB memiliki API yang diekspos melalui prosedur tersimpan, tetapi prosedur tersimpan dapat memaksakan beberapa batasannya sendiri, dan proyek tersebut memiliki semua , untuk berbagai tingkat, menggunakan SQL mentah yang dihasilkan secara dinamis dalam kode untuk mengakses DB.
Memiliki lapisan API pada DB memberikan penggambaran tanggung jawab yang lebih baik antara tim DB dan tim Pengembang dengan mengorbankan beberapa fleksibilitas yang Anda miliki jika kueri disimpan dalam kode, namun proyek PHP cenderung tidak memiliki cukup besar cukup banyak tim untuk mendapatkan manfaat dari penggambaran ini.
Secara konseptual, Anda mungkin harus membuat database Anda berversi. Secara praktis, bagaimanapun, Anda jauh lebih mungkin untuk hanya memiliki kode Anda berversi daripada Anda memiliki database Anda berversi. Anda mungkin akan mengubah kueri saat membuat perubahan pada kode Anda, tetapi jika Anda mengubah kueri dalam prosedur tersimpan yang disimpan di database, maka Anda mungkin tidak akan memeriksanya saat memeriksa kode dan Anda kehilangan banyak manfaat pembuatan versi untuk area signifikan aplikasi Anda.
Terlepas dari apakah Anda memilih untuk tidak menggunakan prosedur tersimpan atau tidak, Anda setidaknya harus memastikan bahwa setiap operasi basis data disimpan dalam fungsi independen daripada disematkan ke setiap skrip halaman Anda - pada dasarnya lapisan API untuk DB Anda yang dipertahankan dan diversi dengan kode Anda. Jika Anda menggunakan prosedur tersimpan, ini secara efektif berarti Anda memiliki dua lapisan API untuk DB Anda, satu dengan kode dan satu dengan DB, yang mungkin Anda rasa tidak perlu memperumit masalah jika proyek Anda tidak memiliki tim yang terpisah. Tentu saja.
Jika masalahnya adalah salah satu dari kerapian kode, ada cara untuk membuat kode dengan SQL macet di dalamnya lebih rapi, dan kelas UserManager yang ditunjukkan di bawah ini adalah cara yang baik untuk memulai - kelas hanya berisi kueri yang berhubungan dengan tabel 'pengguna', setiap kueri memiliki metodenya sendiri di kelas dan kueri diindentasi ke dalam pernyataan persiapan dan diformat seperti Anda memformatnya dalam prosedur tersimpan.
// UserManager.php:
class UserManager
{
function getUsers()
{
$pdo = new PDO(...);
$stmt = $pdo->prepare('
SELECT u.userId as id,
u.userName,
g.groupId,
g.groupName
FROM user u
INNER JOIN group g
ON u.groupId = g.groupId
ORDER BY u.userName, g.groupName
');
// iterate over result and prepare return value
}
function getUser($id) {
// db code here
}
}
// index.php:
require_once("UserManager.php");
$um = new UserManager;
$users = $um->getUsers();
foreach ($users as $user) echo $user['name'];
Namun, jika kueri Anda sangat mirip tetapi Anda memiliki sejumlah besar permutasi dalam kondisi kueri Anda seperti paging yang rumit, pengurutan, pemfilteran, dll, alat pemetaan Objek/Relasional mungkin adalah cara yang harus dilakukan, meskipun proses merombak kode yang ada untuk menggunakan alat ini bisa sangat rumit.
Jika Anda memutuskan untuk menyelidiki alat ORM, Anda harus melihat Propel , komponen ActiveRecord dari Yii , atau ORM PHP raja-ayah, Doktrin . Masing-masing memberi Anda kemampuan untuk membuat kueri secara terprogram ke database Anda dengan segala macam logika yang rumit. Doctrine adalah fitur yang paling lengkap, memungkinkan Anda untuk membuat template database Anda dengan hal-hal seperti Set Bersarang pola pohon di luar kotak.
Dalam hal kinerja, prosedur tersimpan adalah yang tercepat, tetapi umumnya tidak lebih dari sql mentah. Alat ORM dapat memiliki dampak kinerja yang signifikan dalam beberapa cara - kueri yang tidak efisien atau berlebihan, file IO besar saat memuat perpustakaan ORM pada setiap permintaan, pembuatan SQL dinamis pada setiap kueri... semua hal ini dapat berdampak, tetapi penggunaan alat ORM dapat secara drastis meningkatkan daya yang tersedia untuk Anda dengan jumlah kode yang jauh lebih kecil daripada membuat lapisan DB Anda sendiri dengan kueri manual.
Gary Richardson benar sekali, jika Anda akan terus menggunakan SQL dalam kode Anda, Anda harus selalu menggunakan pernyataan yang disiapkan PDO untuk menangani parameter terlepas dari apakah Anda menggunakan kueri atau prosedur tersimpan. Sanitasi masukan dilakukan untuk Anda oleh PDO.
// optional
$attrs = array(PDO::ATTR_PERSISTENT => true);
// create the PDO object
$pdo = new PDO("mysql:host=localhost;dbname=test", "user", "pass", $attrs);
// also optional, but it makes PDO raise exceptions instead of
// PHP errors which are far more useful for debugging
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('INSERT INTO venue(venueName, regionId) VALUES(:venueName, :regionId)');
$stmt->bindValue(":venueName", "test");
$stmt->bindValue(":regionId", 1);
$stmt->execute();
$lastInsertId = $pdo->lastInsertId();
var_dump($lastInsertId);
Peringatan:dengan asumsi ID adalah 1, skrip di atas akan menampilkan string(1) "1"
. PDO->lastInsertId()
mengembalikan ID sebagai string terlepas dari apakah kolom sebenarnya adalah bilangan bulat atau tidak. Ini mungkin tidak akan menjadi masalah bagi Anda karena PHP melakukan casting string ke integer secara otomatis.
Berikut ini akan menampilkan bool(true)
:
// regular equality test
var_dump($lastInsertId == 1);
tetapi jika Anda memiliki kode yang mengharapkan nilainya berupa bilangan bulat, seperti is_int atau "benar-benar 100% sama dengan" operator:
var_dump(is_int($lastInsertId));
var_dump($lastInsertId === 1);
Anda bisa mengalami beberapa masalah.
Sunting: Beberapa diskusi bagus tentang prosedur tersimpan disini