Pdo mengganti parameter tanpa menjalankan kueri. Bagaimana cara bekerja dengan PDO? Panduan lengkap. Memasukkan ke dalam database, metode exec()

Koneksi Basis Data diatur ketika sebuah instance dari kelas PDO dibuat. Tidak masalah driver mana yang Anda pilih untuk digunakan; Anda harus selalu menggunakan kelas PDO. Konstruktornya menerima parameter untuk menentukan sumber database (dikenal sebagai DSN), dan parameter opsional untuk nama pengguna dan kata sandi.

Koneksi ke MySQL:

$dbh = PDO baru("mysql:host=localhost;dbname=test", $user, $pass);

Jika terjadi kesalahan koneksi, pengecualian akan dilempar: objek dari kelas PDOException. Anda dapat menangkapnya jika Anda ingin menangani situasi ini, atau Anda dapat membiarkannya untuk pengendali pengecualian global, yang disetel melalui set_Exception_handler().

Menangani kesalahan koneksi:

coba ( $dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass); foreach($dbh->query('SELECT * from FOO') sebagai $row) ( print_r($ baris); ) $dbh = null; ) catch (PDOException $e) ( die("Error! Selesai. Ini dia... ".$e->getMessage()); )

Perhatian: Jika Anda tidak menangkap pengecualian yang diberikan oleh konstruktor PDO, tindakan default yang diambil oleh mesin zend adalah menghentikan skrip dan menampilkan penelusuran balik. Omong kosong ini akan mengungkapkan semua detail intim komunikasimu dengan database. Yaitu akan menampilkan detail koneksi database terperinci termasuk nama pengguna dan kata sandi! Terserah pada Anda untuk menangkap pengecualian ini, baik secara eksplisit (melalui pernyataan coba tangkap), atau secara implisit melalui set_Exception_handler().

Setelah koneksi database berhasil, koneksi tersebut tetap aktif sepanjang masa pakai objek PDO. Untuk menutup koneksi, Anda harus menghancurkan objek tersebut, memastikan bahwa semua referensi yang tersisa ke objek tersebut telah dihapus - ini dapat dilakukan dengan memberikan nilai NULL ke variabel yang berisi objek tersebut. Jika Anda tidak melakukan ini secara eksplisit, PHP akan secara otomatis menutup koneksi ketika skrip keluar.

Menutup koneksi:

$dbh = PDO baru("mysql:host=localhost;dbname=test", $user, $pass);

Banyak aplikasi web mendapat manfaat dari pembuatan koneksi persisten ke server database. Koneksi persisten tidak ditutup saat skrip keluar, namun di-cache dan digunakan kembali saat skrip lain meminta koneksi menggunakan kredensial koneksi yang sama. Cache koneksi persisten menghindari overhead pembuatan koneksi baru setiap kali skrip perlu berkomunikasi dengan database, sehingga aplikasi web berjalan lebih cepat.

Menyiapkan koneksi permanen:

$dbh = PDO baru("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

Harap diingat: Jika Anda ingin menggunakan koneksi persisten, Anda harus mengaturnya PDO::ATTR_PERSISTENT dalam array opsi driver, yang diteruskan ke konstruktor kelas PDO. Dengan mengatur atribut ini melalui PDO::setAttribute() setelah objek dipakai, driver tidak akan menggunakan tautan persisten. Dan juga, dalam hal ini, Anda tidak akan dapat memperluas kelas PDOStatement untuk beberapa kebutuhan Anda, yaitu. tidak mungkin untuk menginstal: PDO::ATTR_STATEMENT_CLASS

Saya pikir ini saatnya untuk menambah pengalaman saya dan beralih dari fungsi mysql_ ke PDO ketika bekerja dengan database. Pustaka ini merupakan tambahan yang kuat dan cepat untuk PHP. Salah satu kelebihannya adalah dapat bekerja dengan banyak database (MS SQL, MySQL, PostgreSQL, Oracle, dll.). Ciri khas lain dari perpustakaan ini adalah ekspresi yang telah disiapkan, yang disebut pernyataan yang telah disiapkan, yang akan mempercepat pekerjaan dengan database, dan yang paling penting, membuat pertukaran data aman dan melupakan kerentanan seperti injeksi sql. Selain itu, masih ada fitur lain yang sangat berguna. Dalam artikel ini, saya mencoba mengumpulkan contoh-contoh pekerjaan yang sering digunakan sehingga Anda dapat langsung memahami esensi pekerjaan PDO.

Di PHP, ada tiga ekstensi untuk bekerja dengan database MySQL: mysql, mysqli dan PDO. PHP PDO (Objek Data PHP) disertakan dalam PHP 5.1 dan lebih tinggi. Sejauh yang saya pahami, saat ini fungsi untuk bekerja dengan database mysql_ tidak disarankan untuk digunakan, karena pengembangan php_mysql berhenti pada mendukung fungsionalitas MySQL 4.1.3. dan juga tidak mendukung transaksi, antarmuka objek dan rentan terhadap kerentanan saat mengganti nilai ke dalam kueri. Setelah mysql_, ekstensi mysqli muncul (MySQL Ditingkatkan di versi 5), yang mendukung fitur MySQL baru dan menggunakan sintaks OPP dan pemrograman prosedural. Semua perpustakaan ini menggunakan perpustakaan klien MySQL standar (libmysql). Dalam catatan yang sama, mari kita lihat contoh langsung bagaimana bekerja dengan mysql menggunakan ekstensi terbaru - PDO.

Koneksi Basis Data PDO

//contoh koneksi ke MySQL menggunakan PDO $db = new PDO("mysql:host=localhost;dbname=test", $user, $pass);

Setelah koneksi berhasil ke server database tertentu dibuat, objek PDO akan dikembalikan. Objek ini memungkinkan Anda melakukan berbagai macam tugas database.

Jika ada kesalahan koneksi, mekanisme pengecualian akan dipicu - PDOException. Anda harus selalu menggabungkan operasi PDO dalam blok coba/tangkap. Anda dapat menangkap pengecualian jika Anda ingin menangani kesalahan, atau Anda dapat membiarkannya untuk penangan pengecualian global yang Anda buat dengan set_Exception_handler(). PDO memiliki fungsi khusus untuk kesalahan: errorCode() – akan mengembalikan nomor kesalahan, errorInfo() – akan mengembalikan array dengan nomor kesalahan dan deskripsi. Mereka diperlukan karena mode penanganan kesalahan default adalah ERRMODE_SILENT. Dalam hal ini, untuk melihat kesalahan ini Anda harus memanggilnya:

Gema $sambung->errorCode(); echo $sambung->errorInfo();

Untuk menghindari hal ini, dalam mode pengembangan lebih mudah untuk segera mengatur mode penanganan kesalahan yang diinginkan: ATTR_ERRMODE dan ERRMODE_EXCEPTION. Anda juga dapat menentukan pengkodean untuk bekerja dengan database. Hasilnya, kita akan mendapatkan kode koneksi berikut:

Coba ( $db = new PDO("mysql:host=$host;dbname=$dbname", $user, $password); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db-> exec("tetapkan nama utf8"); catch(PDOException $e) ( echo $e->getMessage(); )

Setelah berhasil tersambung ke database, instance kelas PDO dikembalikan ke skrip. $db berisi pegangan database. Koneksi tetap aktif sepanjang umur objek PDO. Untuk menutup koneksi, Anda perlu menghancurkan objek tersebut, memastikan bahwa semua referensi lain ke objek tersebut dihapus. Anda dapat melakukan ini dengan menetapkan nilai NULL pada variabel yang berisi objek. Kecuali Anda melakukan ini secara eksplisit, PHP akan secara otomatis menutup koneksi ketika skrip selesai.

//Menutup koneksi $db = null;

Banyak aplikasi web mendapatkan keuntungan dari pembuatan koneksi persisten ke server database. Koneksi persisten tidak ditutup pada akhir skrip, namun di-cache dan digunakan kembali ketika skrip lain meminta koneksi menggunakan kredensial yang sama. Koneksi persisten mengurangi biaya pembuatan koneksi baru setiap kali skrip perlu mengakses database, sehingga menghasilkan aplikasi web yang lebih cepat.

//Koneksi persisten $dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

Sekarang setelah Anda melihat cara membuka dan menutup koneksi, mari kita lihat contoh lain bekerja dengan PDO. Dalam hal ini, saya akan menunjukkan cara menanyakan database tertentu. Kueri dapat dibuat menggunakan 3 fungsi: exec(), query() dan persiapan+eksekusi.

Eksekutif()

Yang pertama - exec hanya akan mengembalikan jumlah baris yang terlibat atau FALSE jika terjadi kesalahan dan digunakan jika tidak ada data yang dikembalikan, misalnya saat menghapus:

//menggunakan metode exec() coba( $db = new PDO("mysql:host=localhost;dbname=test","pengguna","kata sandi"); $delrows=$db->exec("HAPUS DARI pengguna WHERE id>20"); echo "Jumlah baris yang dihapus: ".$delrows; ) catch(PDOException $e)( echo "Error: ".$e->getMessage(); exit(); ) //Selengkapnya $ db- >exec("HAPUS DARI orang DI MANA 1"); //atau $db->exec("SET zona_waktu = "-8:00""); //atau $db->exec("CREATE TABLE `test`(id INT PRIMARY KEY AUTO_INCREMENT, nama VARCHAR(20) BUKAN NULL DEFAULT "", email VARCHAR(50) BUKAN NULL DEFAULT "")"); //atau $db->exec("SET KARAKTER SET utf8");

Pertanyaan()

Kedua, query() akan mengembalikan hasilnya dalam objek PDOStatement. Juga mengembalikan hasil atau FALSE jika terjadi kesalahan. Anda dapat mempercayainya dengan permintaan sederhana. Anda dapat menggunakan query() dengan syarat (saya benar-benar tidak tahu mengapa ada orang yang membutuhkan ini), tetapi Anda masih harus keluar dari data menggunakan metode PDO::quote

//Pertanyaan sederhana $db->query("SET CHARACTER SET utf8"); $db->query("PILIH * DARI pengguna"); //Anda dapat menghitung jumlah baris $stmt = $db->query("SELECT * FROM table"); $jumlah_baris = $stmt->jumlah baris(); echo $row_count." baris dipilih"; //Opsi lain dengan kuantitas $stmt = $db->query("SELECT * from users"); $baris = $stmt->fetchAll(); $hitungan = hitungan($baris); foreach($rows as $row) ( print_r($row); ) //Query dengan kondisi dan escape $conn->query("SELECT * FROM table WHERE id = " . $conn->quote($id));

terakhirInsertId() mengembalikan ID baris database terakhir yang dimasukkan.

//metode lastInsertId() mengembalikan id dari catatan terakhir $db->query("INSERT INTO users SET name="Vasya",address="Here",email=" [dilindungi email]""); $insertId=$db->lastInsertId();

Pernyataan yang sudah disiapkan.

Cara ketiga - mempersiapkan+melaksanakan - Ekspresi yang Disiapkan, mereka juga menyiapkan instruksi, mereka juga merupakan placeholder pernyataan yang telah disiapkan atau mengikat variabel, memungkinkan Anda mendefinisikan ekspresi satu kali dan kemudian menjalankannya beberapa kali dengan parameter berbeda. Mereka juga memungkinkan Anda memisahkan variabel dari permintaan, yang membuat kode lebih aman dan meningkatkan kecepatan eksekusi. Kode Anda tidak lagi harus mencoba membersihkan data yang ditransfer. Kami hanya akan melakukan ini sekali sebelum menjalankan query database. Untuk melakukan ini kami menggunakan fungsi tersebut Mempersiapkan(); Dibutuhkan query SQL sebagai parameter, tetapi di dalamnya, alih-alih variabel, digunakan label, dalam bentuk tanda tanya '?' atau angka ':1′, atau variabel yang namanya dimulai dengan titik dua ':' . Jika Anda berhenti di tanda tanya (: angka), maka Anda perlu meneruskan array nilai dalam urutan yang sesuai ke fungsi eksekusi. Jika pilihan Anda adalah nama variabel, maka Anda perlu memberikan nilai ke setiap variabel melalui salah satu dari dua fungsi: bindValue(), yang memberikan nilai ke variabel semu, atau bindParam(), yang mengikat variabel semu ke variabel nyata. Parameter ketiga dapat menunjukkan jenis variabel, misalnya $db->bindParam(':id',$id, PDO::PARAM_INT).

//Label tanpa nama coba ( $stmt = $db->prepare("INSERT INTO test (label,color) VALUES (?,?)"); $stmt -> mengeksekusi(array("perfect","green") ) ; ) catch(PDOException $e)( echo "Error: ".$e->getMessage(); exit(); ) //stmt adalah "pegangan status" //Bernama label $stmt = $db->prepare ( "MASUKKAN KE DALAM tes (label,warna) NILAI (:label,:warna)"); $stmt -> jalankan(array("label"=>"sempurna", "warna"=>"hijau")); //Opsi lain $stmt = $db->prepare("INSERT INTO pengguna (nama depan, nama belakang, email) VALUES (:nama depan, :nama belakang, :email)"); $stmt->bindParam(":namadepan", $namadepan); $stmt->bindParam(":namabelakang", $namabelakang); $stmt->bindParam(":email", $email); $nama depan = "John"; $nama belakang = "Smith"; $email = " [dilindungi email]"; $stmt->eksekusi();

Izinkan saya mengingatkan Anda sekali lagi bahwa jika Anda tidak menggunakan ekspresi yang telah disiapkan namun tetap ingin mengamankan data yang dikirimkan, maka ini dapat dilakukan dengan menggunakan fungsi PDO:quote.

data PDO PILIH

Metode Fetch() atau FetchAll() digunakan untuk mengambil data. Sebelum memanggil fungsi tersebut, Anda perlu memberi tahu PDO bagaimana Anda akan mengambil data dari database. PDO::FETCH_ASSOC akan mengembalikan baris sebagai array asosiatif dengan nama bidang sebagai kuncinya. PDO::FETCH_NUM akan mengembalikan string sebagai array numerik. Secara default, pengambilan terjadi dengan PDO::FETCH_BOTH, yang menduplikasi data dengan kunci numerik dan asosiatif, jadi disarankan untuk menentukan satu cara untuk menghindari duplikat array:

$stmt = $db->query("PILIH * dari pengguna"); //Mengatur mode pengambilan $stmt->setFetchMode(PDO::FETCH_ASSOC); while($baris = $stmt->fetch()) ( gema "

" . $baris["nama depan"] . " " . $baris["nama belakang"] . "

"; gema"

" . $baris["email"] . "


"; }

Atau Anda dapat menentukan metode pengambilan dalam metode ->fetch() itu sendiri

$stmt = $db->query("PILIH * DARI tabel"); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) ( echo $row["field1"]." ".$row["field2"]; //etc... ) // Perhatian, contoh dengan LIKE tidak berfungsi! $stmt = $db->prepare("PILIH bidang DARI tabel DIMANA bidang SEPERTI %?%"); $stmt->bindParam(1, $pencarian, PDO::PARAM_STR); $stmt->eksekusi(); //Anda memerlukan ini: $stmt = $db->prepare("SELECT field FROM table WHERE field LIKE ?"); $stmt->bindValue(1, "%$pencarian%", PDO::PARAM_STR); $stmt->eksekusi(); //Contoh lain $stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?"); $stmt->bindValue(1, $id, PDO::PARAM_INT); $stmt->bindValue(2, $nama, PDO::PARAM_STR); $stmt->eksekusi(); $baris = $stmt->fetchAll(PDO::FETCH_ASSOC); //Pilihan lain $stmt = $db->prepare("SELECT * dari pengguna"); $stmt -> jalankan(); while($baris = $stmt->fetch()) ( print_r($baris); )

PEMBARUAN data PDO

Hal ini pada dasarnya terjadi dengan cara yang sama seperti INSERT dan SELECT (dalam hal ini, kita akan kembali menggunakan placeholder bernama):

$stmt = $db->prepare("UPDATE pengguna menyetel email = :email di mana nama belakang=:nama belakang"); $stmt->bindParam(":namabelakang", $namabelakang); $stmt->bindParam(":email", $email); $nama belakang = "Smith"; $email = " [dilindungi email]"; $stmt->eksekusi();

MENGHAPUS Penghapusan terjadi dengan cara paling sederhana:

$db->exec("HAPUS DARI pengguna");

Tentu saja Anda juga dapat menggunakan placeholder bernama saat menghapus.

Jika Anda memiliki template yang sering digunakan saat bekerja dengan ekstensi PHP PDO, saya akan berterima kasih jika Anda membagikannya. Tautan ke panduan

Jika Anda mengalami kesalahan Variabel tidak terdefinisi: DBH... maka Anda dapat membaca cara memperbaikinya.

Google membantu saya menemukan lembar contekan tentang PDO, mungkin seseorang akan merasakan manfaatnya:

PDO (PHP Data Objects) adalah ekstensi PHP yang mengimplementasikan interaksi dengan database menggunakan objek. Keuntungannya adalah tidak ada koneksi ke sistem manajemen database tertentu. PDO mendukung DBMS: MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server dan lainnya.

Mengapa menggunakan PDO

Fungsi mysql di PHP untuk bekerja dengan database sudah lama ketinggalan jaman; saat ini disarankan untuk menggunakan mysqli atau PDO (PHP Data Objects). Selain itu, mysqli adalah perpustakaan yang pada umumnya tidak dimaksudkan untuk digunakan secara langsung dalam kode. Ini dapat berfungsi sebagai bahan bangunan yang baik untuk membuat perpustakaan tingkat yang lebih tinggi. Saat bekerja dengan mysqli, Anda juga harus ingat untuk memastikan keamanan aplikasi Anda, khususnya perlindungan terhadap injeksi SQL. Dalam hal menggunakan PDO (dengan kueri yang telah disiapkan), perlindungan seperti itu sudah siap digunakan; yang utama adalah menerapkan metode yang diperlukan dengan benar.

Uji database dengan tabel

// Dari konsol Windows mysql> BUAT DATABASE `pdo-test` SET KARAKTER utf8 COLLATE utf8_general_ci; GUNAKAN tes pdo; CREATE TABLE kategori (id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), nama VARCHAR(255) NOT NULL); MASUKKAN KE NILAI `kategori` (`nama`) ("Laptop dan tablet"), ("Komputer dan periferal"), ("Komponen PC"), ("Ponsel pintar dan jam tangan pintar"), ("TV dan media ") , ("Permainan dan konsol"), ("Peralatan audio"), ("Peralatan foto dan video"), ("Peralatan dan furnitur kantor"), ("Peralatan jaringan"), ("Peralatan rumah tangga besar"), ( "Produk Dapur"), ("Kecantikan dan Kesehatan"), ("Produk Rumah Tangga"), ("Peralatan"), ("Produk Otomotif");

Instalasi PDO

// Instalasi di Linux sudo apt update sudo apt install php7.2-mysql sudo apt-get install pdo-mysql // Di php.ini tambahkan extension=pdo.so extension=pdo_mysql.so // Di Windows, sebagai aturan, driver sudah terinstal, Anda hanya perlu memeriksa apakah sudah diaktifkan di php.ini extension=php_pdo_mysql.dll

Periksa driver yang tersedia

print_r(PDO::getAvailableDrivers());

Koneksi Basis Data

Koneksi dibuat secara otomatis ketika objek PDO dibuat dari kelas dasarnya.

// Contoh #1. Koneksi sederhana $db = new PDO("mysql:host=localhost;dbname=pdo", "root", "password");

Jika terjadi kesalahan koneksi, PHP akan memunculkan error:

Kesalahan fatal: PDOException Tidak Tertangkap: ... // Contoh #2. Menangani kesalahan koneksi coba ( $dbh = new PDO("mysql:host=localhost;dbname=pdo", "root", "password"); ) catch (PDOException $e) ( print "Error!: " . $e- >dapatkan Pesan();

Dalam contoh koneksi ini, kami menggunakan konstruksi try...catch. Banyak yang berdebat tentang kelayakan penggunaannya. Secara pribadi, saya menggunakan try...catch , itu tidak mengganggu saya.

Permintaan yang disiapkan dan langsung

Ada dua cara untuk mengeksekusi query di PDO:

  • Langsung - terdiri dari satu langkah;
  • Disiapkan - terdiri dari dua langkah.

Permintaan langsung

  • query() digunakan untuk pernyataan yang tidak melakukan perubahan, seperti SELECT. Mengembalikan objek PDOStatemnt yang hasil kuerinya diambil menggunakan metode Fetch() atau FetchAll. Anda dapat membandingkannya dengan sumber daya mysql, yang dikembalikan oleh mysql_query().
  • exec() digunakan untuk pernyataan INSERT, DELETE, UPDATE. Mengembalikan jumlah baris yang diproses oleh permintaan.

Kueri langsung hanya digunakan jika tidak ada variabel dalam kueri dan Anda yakin bahwa kueri tersebut aman dan di-escape dengan benar.

$stmt = $db->query("PILIH * DARI kategori"); while ($baris = $stmt->fetch()) ( gema "

"; print_r($baris); )

Kueri yang sudah disiapkan

Jika setidaknya satu variabel diteruskan ke permintaan, maka permintaan ini harus dieksekusi hanya melalui ekspresi yang telah disiapkan. Apa maksudnya? Ini adalah kueri SQL biasa, di mana penanda khusus ditempatkan sebagai pengganti variabel - placeholder. PDO mendukung placeholder posisional (?), yang urutan variabelnya penting, dan diberi nama placeholder (:nama), yang urutannya tidak penting. Contoh:

$sql = "PILIH nama DARI kategori WHERE id = ?"; $sql = "PILIH nama DARI kategori DIMANA nama = :nama";

Untuk mengeksekusi query seperti itu, pertama-tama harus disiapkan menggunakan metode prep(). Ini juga mengembalikan pernyataan PDO, tetapi belum ada data apa pun. Untuk mendapatkannya, kita perlu menjalankan permintaan ini, setelah sebelumnya memasukkan variabel kita ke dalamnya. Anda dapat meneruskannya dengan dua cara: Paling sering, Anda cukup menjalankan metode mengeksekusi(), meneruskannya ke array dengan variabel:

$stmt = $pdo->prepare("PILIH `nama` DARI kategori WHERE `id` = ?"); $stmt->eksekusi([$id]); $stmt = $pdo->prepare("PILIH `nama` DARI kategori WHERE `nama` = :nama"); $stmt->eksekusi(["nama" => $nama]);

Seperti yang Anda lihat, dalam kasus placeholder bernama, array yang kuncinya harus cocok dengan nama placeholder harus diteruskan ke mengeksekusi(). Anda kemudian dapat mengambil hasil kueri:

$id = 1; $stmt = $db->prepare("PILIH * DARI kategori DIMANA `id` = ?"); $stmt->eksekusi([$id]); $kategori = $stmt->mengambil(PDO::FETCH_LAZY); gema "

"; print_r($kategori);

PENTING! Kueri yang telah disiapkan adalah alasan utama menggunakan PDO karena ini adalah satu-satunya cara aman untuk mengeksekusi kueri SQL yang melibatkan variabel.

Menerima data. ambil() metode

Kita telah mengenal metode ambil(), yang digunakan untuk mendapatkan baris dari database secara berurutan. Metode ini merupakan analog dari fungsi mysq_fetch_array() dan fungsi serupa, tetapi cara kerjanya berbeda: alih-alih banyak fungsi, satu fungsi digunakan di sini, tetapi perilakunya ditentukan oleh parameter yang diteruskan. Detail tentang parameter ini akan ditulis, dan sebagai rekomendasi singkat, saya menyarankan Anda untuk menggunakan mengambil() dalam mode FETCH_LAZY

$id = 1; $stmt = $db->prepare("PILIH * DARI kategori DIMANA `id` = ?"); $stmt->eksekusi([$id]); while ($row = $stmt->fetch(PDO::FETCH_LAZY)) ( echo "Nama kategori: ".$row->name; )

Dalam mode ini, tidak ada memori tambahan yang terbuang, dan selain itu, kolom dapat diakses dengan salah satu dari tiga cara - melalui indeks, nama, atau properti (melalui ->). Kerugian dari mode ini adalah tidak berfungsi dengan FetchAll()

Menerima data. metode ambilKolom()

Pernyataan PDO juga memiliki metode untuk mendapatkan nilai dari satu kolom. Akan sangat mudah jika kita hanya meminta satu bidang - dalam hal ini, jumlah kode akan berkurang secara signifikan:

$id = 1; $stmt = $db->prepare("PILIH `nama` DARI kategori WHERE `id` = ?"); $stmt->eksekusi([$id]); $nama = $stmt->fetchColumn(); echo "Nama kategori: ".$nama;

Menerima data. metode ambilSemua()

$data = $db->query("PILIH * DARI kategori")->fetchAll(PDO::FETCH_ASSOC); foreach ($data sebagai $k => $v)( echo "Nama kategori: ".$v["nama"]."
"; }

PDO dan operator LIKE

Saat bekerja dengan kueri yang telah disiapkan, Anda harus memahami bahwa placeholder dapat menggantikannya hanya string atau angka. Bukan kata kunci, bukan pengidentifikasi, bukan bagian dari string atau kumpulan string melalui placeholder kamu tidak bisa menggantikannya. Oleh karena itu, untuk LIKE Anda harus terlebih dahulu menyiapkan seluruh string pencarian, lalu menggantinya ke dalam query:

$pencarian = "komp"; $query = "PILIH * DARI kategori DIMANA `nama` SEPERTI ?"; $params = ["%$pencarian%"]; $stmt = $db->persiapan($query); $stmt->eksekusi($params); $data = $stmt->fetchAll(PDO::FETCH_ASSOC); $i = 1; foreach ($data sebagai $kategori)( echo $i++ . ". " . $kategori["nama"]."
"; }

Di sinilah masalah mungkin timbul! Pencarian mungkin tidak berhasil karena Anda menerima data dari database dengan pengkodean yang salah. Anda perlu menambahkan pengkodean ke koneksi jika tidak tercantum di sana!

$db = PDO baru("mysql:host=localhost;dbname=pdo;charset=utf8", "root", "");

PDO dan operator LIMIT

Penting! Saat PDO berjalan dalam mode emulasi, semua data yang diteruskan langsung ke mengeksekusi() diformat sebagai string. Artinya, mereka di-escape dan dibingkai dalam tanda kutip. Oleh karena itu BATAS?,? berubah menjadi LIMIT "10", "10" dan jelas menyebabkan kesalahan sintaksis dan, karenanya, array data kosong.

Solusi #1: Nonaktifkan mode emulasi:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, salah);

Solusi #2: Ikat nomor-nomor ini menggunakan bindValue() , sehingga memaksanya menjadi tipe PDO::PARAM_INT:

$batas = 3; $stm = $db->prepare("PILIH * DARI BATAS kategori ?"); $stm->bindValue(1, $batas, PDO::PARAM_INT); $stm->eksekusi(); $data = $stm->fetchAll(); gema "

"; print_r($data);

Operator PDO dan IN

Saat memilih dari tabel, perlu untuk mengambil catatan yang sesuai dengan semua nilai array.

$arr = ; $dalam = str_repeat("?,",hitung($arr) - 1) . "?"; $sql = "PILIH * DARI kategori DIMANA `id` DI ($dalam)"; $stm = $db->persiapan($sql); $stm->eksekusi($arr); $data = $stm->fetchAll(); gema "

"; print_r($data);

Menambahkan entri

$nama = "Kategori baru"; $query = "MASUKKAN KE `kategori` (`nama`) NILAI (:nama)"; $params = [ ":nama" => $nama ]; $stmt = $pdo->persiapan($query); $stmt->eksekusi($params);

Mengubah entri

$id = 1; $nama = "Entri diubah"; $query = "PERBARUI `kategori` SET `nama` = :nama WHERE `id` = :id"; $params = [ ":id" => $id, ":nama" => $nama ]; $stmt = $pdo->persiapan($query); $stmt->eksekusi($params);

Menghapus entri

$id = 1; $query = "HAPUS DARI `kategori` DI MANA `id` = ?"; $params = [$id]; $stmt = $pdo->persiapan($query); $stmt->eksekusi($params);

Menggunakan transaksi

coba ( // Awal transaksi $pdo->beginTransaction(); // ... kode // Jika semuanya berhasil sebagai hasil dari mengeksekusi kode kita, // maka kita akan mencatat hasil ini $pdo->commit() ; ) catch (Pengecualian $e) ( // Jika tidak, kembalikan transaksi. $pdo->rollBack(); echo "Error: " . $e->getMessage(); )

Penting! Transaksi di PDO hanya berfungsi pada tabel InnoDB

Pada artikel ini, kita mengenal konsep dasar PDO, instalasinya, koneksi ke database, dan opsi paling sederhana untuk memilih, mengubah, dan menghapus data. Kami akan melihat beberapa topik lagi terkait PDO di postingan mendatang.

Memberikan metode mempersiapkan ekspresi dan bekerja dengan objek yang dapat membuat Anda lebih produktif!

Pengantar PDO

"PDO - Objek Data PHP adalah lapisan akses basis data yang menyediakan metode terpadu untuk mengakses basis data yang berbeda."

Itu tidak bergantung pada sintaks basis data tertentu dan memungkinkan Anda dengan mudah beralih ke tipe dan platform basis data lain hanya dengan mengubah string koneksi dalam banyak kasus.

Pelajaran ini bukan merupakan deskripsi proses pengerjaan SQL. Ini ditujukan bagi mereka yang menggunakan ekstensi mysql atau mysqli untuk membantu mereka beralih ke PDO yang lebih kuat dan portabel.

Dukungan basis data

Ekstensi ini mendukung database apa pun yang memiliki driver PDO. Driver saat ini tersedia untuk tipe database berikut:

  • PDO_DBLIB (TDS Gratis / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (Server Dinamis IBM Informix)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Antarmuka Panggilan Oracle)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC dan win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 dan SQLite 2)
  • PDO_4D (4D)

Agar sistem dapat berfungsi, cukup menginstal driver yang benar-benar diperlukan saja. Anda bisa mendapatkan daftar driver yang tersedia di sistem sebagai berikut:

Print_r(PDO::getAvailableDrivers());

Koneksi

Basis data yang berbeda mungkin memiliki metode koneksi yang sedikit berbeda. Metode untuk menghubungkan ke beberapa database populer ditunjukkan di bawah ini. Anda akan melihat bahwa tiga yang pertama identik satu sama lain, dan hanya SQLite yang memiliki sintaksis tertentu.


coba ( # MS SQL Server dan Sybase dengan PDO_DBLIB $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass"); $DBH = new PDO("sybase:host=$host ;dbname=$dbname, $user, $pass"); # MySQL dengan PDO_MYSQL $DBH = PDO baru("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = PDO baru("sqlite:my/database/path/database.db"); catch(PDOException $e) ( echo $e->getMessage(); )

Perhatikan bloknya coba/tangkap- Anda harus selalu menggabungkan operasi PDO dalam satu blok coba/tangkap dan gunakan mekanisme pengecualian. Biasanya hanya satu koneksi yang dibuat, contoh kami menunjukkan beberapa koneksi untuk menunjukkan sintaksisnya. $DBH berisi pegangan database dan akan digunakan sepanjang tutorial kita.

Anda dapat menutup koneksi apa pun dengan menyetel pegangan ke batal.

# Tutup koneksi $DBH = null;

Anda dapat mempelajari lebih lanjut tentang opsi spesifik dan string koneksi untuk berbagai database dari dokumen di PHP.net.

Pengecualian dan PDO

PDO dapat menggunakan pengecualian untuk menangani kesalahan. Artinya semua operasi PDO harus dimasukkan ke dalam satu blok coba/tangkap. PDO dapat memunculkan tiga tingkat kesalahan, tingkat kontrol kesalahan dipilih dengan mengatur atribut mode kontrol kesalahan untuk deskriptor database:

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Terlepas dari set level kontrol, kesalahan koneksi selalu menimbulkan pengecualian dan oleh karena itu harus selalu diapit dalam blok coba/tangkap.

PDO::ERRMODE_SILENT

Tingkat kontrol kesalahan diatur secara default. Pada tingkat ini, kesalahan dihasilkan berdasarkan prinsip yang sama seperti pada ekstensi mysql atau mysqli. Dua tingkat kontrol kesalahan lainnya lebih cocok untuk gaya pemrograman KERING (Jangan Ulangi Diri Sendiri).

PDO::ERRMODE_WARNING

Pada tingkat pengendalian kesalahan ini, peringatan standar PHP dihasilkan dan program dapat terus dijalankan. Level ini nyaman untuk debugging.

PDO::ERRMODE_EXCEPTION

Tingkat pengendalian kesalahan ini harus digunakan di sebagian besar situasi. Pengecualian dibuat untuk menangani kesalahan secara hati-hati dan menyembunyikan data yang dapat membantu seseorang meretas sistem Anda. Di bawah ini adalah contoh yang menunjukkan manfaat pengecualian:

# Hubungkan ke database coba ( $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ; # Salah mengetik DELECT alih-alih SELECT! $DBH->prepare("DELECT name FROM people"); catch(PDOException $e) ( echo "Maaf. Tetapi operasi tidak dapat diselesaikan."; file_put_contents("PDOErrors.txt " , $e->getMessage(), FILE_APPEND);

Ada kesalahan yang disengaja dalam pernyataan SELECT di sini. Ini akan menimbulkan pengecualian. Pengecualian akan mengirimkan deskripsi kesalahan ke file log dan menampilkan pesan kepada pengguna.

Memasukkan dan memperbarui data

Memasukkan data baru atau memperbarui data yang sudah ada adalah salah satu operasi database umum yang paling umum digunakan. Saat menggunakan PDO, itu dipecah menjadi dua tahap. Segala sesuatu yang dijelaskan dalam bab ini berlaku untuk kedua operasi tersebut. MEMPERBARUI Dan MENYISIPKAN.


Berikut ini contoh jenis penyisipan data yang paling sering digunakan:

# STH adalah "pegangan status" $STH = $DBH->prepare("INSERT INTO folks (first_name) value ("Cathy")"); $STH->eksekusi();

Tentu saja, Anda dapat melakukan operasi ini menggunakan metode ini eksekutif(), dan jumlah panggilan akan berkurang satu. Namun lebih baik menggunakan metode yang lebih panjang untuk mendapatkan manfaat dari ekspresi yang telah disiapkan. Meskipun Anda hanya ingin menggunakannya sekali, ekspresi yang telah disiapkan akan membantu Anda melindungi dari serangan pada sistem Anda.

Ekspresi yang Disiapkan

Pernyataan yang telah disiapkan adalah pernyataan SQL yang telah dikompilasi sebelumnya yang dapat dieksekusi berkali-kali dengan hanya mengirimkan data ke server. Mereka mempunyai keuntungan tambahan karena secara otomatis mengisi template dengan data dalam bentuk perlindungan terhadap serangan melalui lampiran kode SQL.

Anda dapat menggunakan ekspresi yang telah disiapkan dengan menyertakan templat dalam kode SQL Anda. Di bawah ini ada 3 contoh: satu tanpa templat, satu dengan templat tanpa nama, satu lagi dengan templat bernama.

# tanpa templat - terbuka terhadap serangan injeksi SQL! $STH = $DBH->("MASUKKAN KE nilai orang (nama, alamat, kota) ($nama, $tambahan, $kota)"); # pola tanpa nama $STH = $DBH->("INSERT INTO folk (nama, alamat, kota) nilai (?, ?, ?); # pola bernama $STH = $DBH->("INSERT INTO folk (nama , addr , kota) nilai (:nama, :addr, :kota)");

Sebaiknya hindari penggunaan cara pertama. Pilihan pola bernama atau tanpa nama memengaruhi cara Anda mengatur data untuk ekspresi ini.

Templat tanpa nama

# menetapkan variabel ke setiap template, diindeks dari 1 hingga 3 $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $kota); # Sisipkan satu baris $name = "Dima" $addr = "Lizyukova St."; $kota = "Moskow"; $STH->eksekusi(); # Masukkan baris lain $name = "Senya" $addr = "Jalan buntu komunis"; $kota = "Petrus"; $STH->eksekusi();

Operasi berlangsung dalam dua tahap. Pada langkah pertama, variabel ditugaskan ke template. Kemudian, variabel diberi nilai dan ekspresi dijalankan. Untuk mengirim potongan data berikutnya, Anda perlu mengubah nilai variabel dan menjalankan ekspresi lagi.

Terlihat agak rumit untuk ekspresi dengan banyak parameter? Tentu. Namun, jika data Anda disimpan dalam array, maka semuanya akan menjadi sangat singkat:

# Data yang akan dimasukkan $data = array("Monya", "Forget-Me-Not Avenue", "Zakutaysk"); $STH = $DBH->("MASUKKAN KE nilai orang (nama, alamat, kota) (?, ?, ?)"); $STH->eksekusi($data);

Data dalam array diganti ke dalam templat sesuai urutan kemunculannya. $data ke templat pertama, $data ke templat kedua, dan seterusnya. Namun, jika array diindeks dalam urutan yang berbeda, maka operasi seperti itu tidak akan dilakukan dengan benar. Anda perlu memastikan bahwa urutan polanya sesuai dengan urutan data dalam array.

Templat Bernama

Berikut ini contoh penggunaan templat bernama:

# Argumen pertama pada fungsi adalah nama templat yang diberi nama # Templat yang diberi nama selalu diawali dengan titik dua $STH->bindParam(":name", $name);

Anda dapat menggunakan pintasan, tetapi pintasan tersebut berfungsi dengan array terkait. Contoh:

# Data yang akan dimasukkan $data = array("name" => "Michelle", "addr" => "Kuznechny Lane", "city" => "Cnjkbwf"); # Singkatan $STH = $DBH->("INSERT INTO orang (nama, alamat, kota) nilai (:nama, :addr, :kota)"); $STH->eksekusi($data);

Kunci tabel Anda tidak memerlukan titik dua, namun harus tetap cocok dengan nama templat. Jika Anda menggunakan array dari array, Anda dapat mengulanginya dan cukup menelepon menjalankan untuk setiap kumpulan data.

Fitur bagus lainnya dari templat bernama adalah kemampuan untuk memasukkan objek langsung ke database Anda ketika properti dan nama bidang cocok. Contoh:

# Orang kelas objek sederhana ( public $name; public $addr; public $city; function __construct($n,$a,$c) ( $this->name = $n; $this->addr = $a; $ ini->kota = $c; ) # dll. ... ) $cathy = orang baru("Katya","Lenin Avenue","Mozhaisk"); # Jalankan: $STH = $DBH->("INSERT INTO orang (nama, alamat, kota) value (:nama, :addr, :kota)"); $STH->eksekusi((array)$cathy);

Mengubah tipe objek menjadi susunan V menjalankan menyebabkan properti diperlakukan sebagai kunci array.

Menerima data


Metode pengidentifikasi negara digunakan untuk memperoleh data -> ambil(). Sebelum memanggil metode tersebut mengambil() Anda perlu memberi tahu PDO bagaimana Anda akan mengambil data dari database. Anda dapat memilih opsi berikut:

  • PDO::FETCH_ASSOC: mengembalikan array yang diindeks berdasarkan nama kolom
  • PDO::FETCH_BOTH (bawaan): mengembalikan array yang diindeks berdasarkan nama kolom dan nomor
  • PDO::FETCH_BOUND: Menetapkan nilai kolom Anda ke sekumpulan variabel menggunakan metode ini ->bindColumn()
  • PDO::FETCH_CLASS: memberikan nilai kolom ke properti kelas bernama; jika properti terkait tidak ada, maka properti tersebut akan dibuat
  • PDO::FETCH_INTO: memperbarui instance kelas bernama yang sudah ada
  • PDO::FETCH_LAZY: kombinasi PDO::FETCH_BOTH/PDO::FETCH_OBJ, membuat nama variabel objek saat digunakan
  • PDO::FETCH_NUM: mengembalikan array yang diindeks berdasarkan nomor kolom
  • PDO::FETCH_OBJ: mengembalikan objek anonim dengan nama properti yang sesuai dengan nama kolom

Pada kenyataannya, situasi dasar diselesaikan dengan menggunakan tiga opsi: FETCH_ASSOC, FETCH_CLASS Dan FETCH_OBJ. Untuk mengatur metode ekstraksi data:

$STH->setFetchMode(PDO::FETCH_ASSOC);

Anda juga dapat mengatur metode pengambilan data secara langsung di pemanggilan metode -> ambil().

FETCH_ASSOC

Jenis pengambilan data ini membuat array asosiatif yang diindeks berdasarkan nama kolom. Ini harus diketahui oleh mereka yang menggunakan ekstensi mysql/mysqli. Contoh contoh data:

$STH = $DBH->query("PILIH nama, alamat, kota dari orang"); # Atur mode pengambilan data $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["name"] . "\n"; echo $row["addr"] . "\n"; echo $row["city"] . "\N" ;

Siklus ketika terus mengulangi hasil sampel satu baris pada satu waktu hingga selesai.

FETCH_OBJ

Dengan jenis pengambilan data ini, objek kelas dibuat std untuk setiap baris data yang diterima:

$STH = $DBH->query("PILIH nama, alamat, kota dari orang"); # Atur mode pengambilan data $STH->setFetchMode(PDO::FETCH_OBJ); # tampilkan hasilnya while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . " \ N"; )

FETCH_CLASS

Dengan jenis ekstraksi ini, data ditempatkan langsung ke kelas yang Anda pilih. Saat menggunakan FETCH_CLASS properti objek Anda disetel SEBELUM memanggil konstruktor. Ini sangat penting. Jika properti yang sesuai dengan nama kolom tidak ada, maka properti tersebut akan dibuat (seperti publik) untukmu.

Artinya, jika data memerlukan transformasi setelah diambil dari database, hal ini dapat dilakukan secara otomatis oleh objek Anda segera setelah dibuat.

Misalnya, bayangkan sebuah situasi di mana alamat harus disembunyikan sebagian untuk setiap entri. Kita dapat menyelesaikan tugas tersebut dengan memanipulasi properti di konstruktor:

Kelas secret_person ( public $name; public $addr; public $city; public $other_data; function __construct($other = "") ( $this->address = preg_replace("//", "x", $this-> alamat); $ini->data_lainnya = $lainnya;

Setelah data diekstraksi ke dalam kelas, semua karakter huruf kecil a-z di alamat akan diganti dengan karakter x. Sekarang, dengan menggunakan kelas dan mengambil data, transformasi terjadi sepenuhnya secara transparan:

$STH = $DBH->query("PILIH nama, alamat, kota dari orang"); $STH->setFetchMode(PDO::FETCH_CLASS, "orang_rahasia"); while($obj = $STH->fetch()) ( echo $obj->addr; )

Jika alamatnya adalah 'Leninsky Prospekt 5' Anda akan melihat 'Lxxxxxxxxxx xx-x 5'. Tentu saja, ada situasi di mana Anda ingin konstruktor dipanggil sebelum data ditugaskan. PDO mempunyai sarana untuk melaksanakan hal ini:

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "secret_person");

Sekarang, ketika Anda mengulangi contoh sebelumnya dengan mode yang disetel PDO::FETCH_PROPS_LATE alamat tidak akan disembunyikan sejak konstruktor dipanggil dan properti ditetapkan.

Jika perlu, Anda bisa meneruskan argumen ke konstruktor saat mengekstraksi data ke dalam objek:

$STH->setFetchMode(PDO::FETCH_CLASS, "orang_rahasia", array("barang"));

Jika Anda perlu meneruskan data yang berbeda ke konstruktor untuk setiap objek, Anda dapat mengatur mode pengambilan data di dalam metode mengambil:

$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // melakukan sesuatu $i++ )

Beberapa metode bermanfaat lainnya

Karena PDO tidak dapat dijelaskan secara lengkap dalam artikel singkat, kami akan menyajikan beberapa metode berguna untuk melakukan operasi dasar.

$DBH->lastInsertId();

Metode ->InsertId terakhir() selalu dipanggil oleh pegangan database (bukan pegangan status) dan mengembalikan nilai id yang bertambah secara otomatis dari baris terakhir yang disisipkan untuk koneksi tertentu.

$DBH->exec("HAPUS DARI orang DI MANA 1"); $DBH->exec("SET zona_waktu = "-8:00"");

Metode -> eksekutif() digunakan untuk berbagai operasi tambahan.

$aman = $DBH->quote($tidak aman);

Metode -> kutipan() string kuota sehingga dapat digunakan dalam kueri. Ini adalah cadangan Anda jika ekspresi yang telah disiapkan tidak digunakan.

$rows_affected = $STH->rowCount();

Metode ->Jumlah baris() mengembalikan nilai bilangan bulat, menunjukkan jumlah baris yang diproses oleh operasi. Di PDO versi terbaru, menurut laporan bug (http://bugs.php.net/40822), metode ini tidak berfungsi dengan ekspresi MEMILIH. Jika Anda mengalami masalah dan tidak bisa update PHP, Anda bisa mendapatkan jumlah barisnya dengan cara berikut:

$sql = "PILIH JUMLAH(*) DARI orang"; if ($STH = $DBH->query($sql)) ( # Periksa jumlah baris if ($STH->fetchColumn() > 0) ( # Seharusnya ada kode SELECT di sini) else ( echo "Ada tidak ada baris yang cocok dengan kueri." ; ) )

Saya harap Anda menyukai pelajaran ini!

  • Terjemahan

Banyak pengembang PHP yang terbiasa menggunakan ekstensi mysql dan mysqli untuk bekerja dengan database. Tapi sejak versi 5.1 di PHP ada cara yang lebih nyaman - Objek Data PHP. Kelas ini, disingkat PDO, menyediakan metode untuk bekerja dengan objek dan menyiapkan pernyataan yang akan meningkatkan produktivitas Anda secara signifikan!

Pengantar PDO

"PDO - Objek Data PHP adalah lapisan yang menawarkan cara universal untuk bekerja dengan banyak database."

Hal ini meninggalkan kekhawatiran terhadap fitur sintaksis berbagai DBMS kepada pengembang, namun membuat proses peralihan antar platform menjadi lebih mudah. Seringkali ini hanya memerlukan perubahan string koneksi database.


Artikel ini ditulis untuk orang-orang yang menggunakan mysql dan mysqli untuk membantu mereka bermigrasi ke PDO yang lebih kuat dan fleksibel.

dukungan DBMS

Ekstensi ini dapat mendukung sistem manajemen basis data apa pun yang memiliki driver PDO. Pada saat penulisan, driver berikut tersedia:
  • PDO_CUBRID (CUBRID)
  • PDO_DBLIB (TDS Gratis / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (Server Dinamis IBM Informix)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Antarmuka Panggilan Oracle)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC dan win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 dan SQLite 2)
  • PDO_SQLSRV (Microsoft SQL Server)
  • PDO_4D (4D)
Namun, tidak semuanya ada di server Anda. Anda dapat melihat daftar driver yang tersedia seperti ini:
print_r(PDO::getAvailableDrivers());

Koneksi

Metode untuk menghubungkan ke DBMS yang berbeda mungkin sedikit berbeda. Di bawah ini adalah contoh koneksi ke yang paling populer. Anda akan melihat bahwa tiga yang pertama memiliki sintaks yang identik, tidak seperti SQLite.
coba ( # MS SQL Server dan Sybase melalui PDO_DBLIB $DBH = new PDO("mssql:host=$host;dbname=$dbname", $user, $pass); $DBH = new PDO("sybase:host=$host ;dbname=$dbname", $user, $pass); # MySQL melalui PDO_MYSQL $DBH = PDO baru("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = PDO baru("sqlite:my/database/path/database.db"); catch(PDOException $e) ( echo $e->getMessage(); )
Harap perhatikan blok coba/tangkap - selalu ada gunanya menggabungkan semua operasi PDO Anda di dalamnya dan menggunakan mekanisme pengecualian (lebih lanjut tentang ini nanti).

$DBH adalah singkatan dari "database handle" dan akan digunakan di seluruh artikel.

Anda dapat menutup koneksi apa pun dengan mendefinisikan ulang variabelnya menjadi nol.
# menutup koneksi $DBH = null;
Informasi lebih lanjut mengenai topik opsi khusus dari berbagai DBMS dan metode koneksinya dapat ditemukan di php.net.

Pengecualian dan PDO

PDO dapat memberikan pengecualian pada kesalahan, jadi semuanya harus berada dalam blok coba/tangkap. Segera setelah membuat koneksi, PDO dapat dialihkan ke salah satu dari tiga mode kesalahan:
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Namun perlu dicatat bahwa kesalahan saat mencoba menyambung akan selalu memunculkan pengecualian.

PDO::ERRMODE_SILENT

Ini adalah modus bawaan. Anda mungkin akan menggunakan hal yang kira-kira sama untuk menangkap kesalahan pada ekstensi mysql dan mysqli. Dua mode berikutnya lebih cocok untuk pemrograman KERING.

PDO::ERRMODE_WARNING

Mode ini akan menyebabkan Peringatan standar dan memungkinkan skrip untuk terus dijalankan. Nyaman untuk debugging.

PDO::ERRMODE_EXCEPTION

Dalam kebanyakan situasi, jenis kontrol eksekusi skrip ini lebih disukai. Ini memberikan pengecualian, memungkinkan Anda dengan cerdik menangani kesalahan dan menyembunyikan informasi sensitif. Seperti misalnya di sini:
# sambungkan ke database coba ( $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ; # Sial! Saya mengetik DELECT alih-alih SELECT! $DBH->prepare("DELECT name FROM people")->execute(); ) catch(PDOException $e) ( echo "Houston, kita punya masalah."; file_put_contents( "PDOErrors" .txt", $e->getMessage(), FILE_APPEND); )
Ada kesalahan sintaksis dalam ekspresi SQL yang akan memunculkan pengecualian. Kami dapat mencatat rincian kesalahan dalam file log dan memberi petunjuk kepada pengguna dalam bahasa manusia bahwa sesuatu telah terjadi.

Sisipkan dan Perbarui

Memasukkan data baru dan memperbarui data yang sudah ada adalah beberapa operasi database yang paling umum. Dalam kasus PDO, proses ini biasanya terdiri dari dua langkah. (Bagian selanjutnya adalah tentang UPDATE dan INSERT)


Contoh sepele memasukkan data baru:
# STH berarti "Pegangan Pernyataan" $STH = $DBH->prepare("INSERT INTO folks (first_name) value ("Cathy")"); $STH->eksekusi();
Sebenarnya, Anda dapat melakukan hal yang sama dengan satu metode exec(), namun metode dua langkah memberikan semua manfaat dari pernyataan yang disiapkan. Mereka membantu melindungi terhadap injeksi SQL, jadi masuk akal untuk menggunakannya bahkan untuk kueri satu kali.

Pernyataan yang Disiapkan

Menggunakan pernyataan yang telah disiapkan memperkuat perlindungan terhadap injeksi SQL.

Pernyataan yang Disiapkan adalah pernyataan SQL yang telah dikompilasi sebelumnya yang dapat dieksekusi berulang kali dengan hanya mengirimkan kumpulan data berbeda ke server. Keuntungan tambahannya adalah tidak mungkin melakukan injeksi SQL melalui data yang digunakan dalam placeholder.

Di bawah ini adalah tiga contoh pernyataan yang telah disiapkan.
# tanpa placeholder - pintu ke injeksi SQL terbuka! $STH = $DBH->prepare("INSERT INTO orang (nama, alamat, kota) nilai ($nama, $tambahan, $kota)"); # placeholder yang tidak disebutkan namanya $STH = $DBH->prepare("INSERT INTO orang (nama, alamat, kota) nilai (?, ?, ?)"); # bernama placeholder $STH = $DBH->prepare("INSERT INTO orang (nama, alamat, kota) nilai (:nama, :tambahan, :kota)");
Contoh pertama di sini hanya untuk perbandingan dan sebaiknya dihindari. Perbedaan antara placeholder tanpa nama dan bernama adalah cara Anda meneruskan data ke pernyataan yang telah disiapkan.

Placeholder tanpa nama

# menetapkan variabel ke setiap placeholder, dengan indeks dari 1 hingga 3 $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $kota); # masukkan satu baris $name = "Daniel" $addr = "1 Jalan Jahat"; $kota = "Ketinggian Arlington"; $STH->eksekusi(); # masukkan baris lain, dengan data berbeda $name = "Steve" $addr = "5 Circle Drive"; $kota = "Schaumburg"; $STH->eksekusi();
Ada dua langkah di sini. Pada bagian pertama, kami menetapkan variabel ke semua placeholder (baris 2-4). Kemudian kami menetapkan nilai ke variabel-variabel ini dan menjalankan kueri. Untuk mengirim kumpulan data baru, cukup ubah nilai variabel dan jalankan permintaan lagi.

Jika ekspresi SQL Anda memiliki banyak parameter, maka menetapkan variabel ke masing-masing parameter akan sangat merepotkan. Dalam kasus seperti ini, Anda dapat menyimpan data dalam array dan meneruskannya:
# kumpulan data yang akan kita masukkan $data = array("Cathy", "9 Jalan Gelap dan Berkelok-kelok", "Cardiff"); $STH = $DBH->prepare("INSERT INTO orang (nama, alamat, kota) nilai (?, ?, ?)"); $STH->eksekusi($data);
$data akan dimasukkan sebagai pengganti placeholder pertama, $data sebagai pengganti placeholder kedua, dan seterusnya. Namun hati-hati: jika indeks Anda kacau, ini tidak akan berhasil.

Placeholder bernama

# argumen pertama adalah nama placeholder # biasanya dimulai dengan titik dua # meskipun dapat digunakan tanpa titik dua $STH->bindParam(":name", $name);
Di sini Anda juga dapat meneruskan array, tetapi harus bersifat asosiatif. Kuncinya harus, seperti yang Anda duga, nama-nama placeholder.
# data yang kita masukkan $data = array("name" => "Cathy", "addr" => "9 Dark and Twisty", "city" => "Cardiff"); $STH = $DBH->prepare("INSERT INTO orang (nama, alamat, kota) nilai (:nama, :addr, :kota)"); $STH->eksekusi($data);
Salah satu kemudahan menggunakan placeholder bernama adalah kemampuan untuk memasukkan objek langsung ke database jika nama properti cocok dengan nama parameter. Misalnya, Anda dapat memasukkan data seperti ini:
# kelas untuk orang kelas objek sederhana ( public $name; public $addr; public $city; function __construct($n,$a,$c) ( $this->name = $n; $this->addr = $ a ; $ini->kota = $c; ) # seterusnya... ) $cathy = orang baru("Cathy","9 Gelap dan Berkelok-kelok","Cardiff"); # dan inilah bagian yang menarik $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value ​​(:name, :addr, :city)"); $STH->eksekusi((array)$cathy);
Mengonversi objek menjadi array selama eksekusi() menyebabkan properti diperlakukan sebagai kunci array.

Pengambilan sampel data



Data dapat diambil menggunakan metode ->fetch(). Sebelum menyebutnya, disarankan untuk secara eksplisit menunjukkan dalam bentuk apa Anda memerlukannya. Ada beberapa pilihan:
  • PDO::FETCH_ASSOC: mengembalikan array dengan nama kolom sebagai kunci
  • PDO::FETCH_BOTH (bawaan): mengembalikan array dengan indeks baik berupa nama kolom maupun nomor serinya
  • PDO::FETCH_BOUND: memberikan nilai kolom ke variabel terkait yang ditentukan menggunakan metode ->bindColumn()
  • PDO::FETCH_CLASS: memberikan nilai kolom ke properti yang sesuai dari kelas yang ditentukan. Jika tidak ada properti untuk beberapa kolom, maka akan dibuat
  • PDO::FETCH_INTO: memperbarui instance yang ada dari kelas tertentu
  • PDO::FETCH_LAZY: menggabungkan PDO::FETCH_BOTH dan PDO::FETCH_OBJ
  • PDO::FETCH_NUM: mengembalikan array dengan kunci sebagai nomor kolom
  • PDO::FETCH_OBJ: mengembalikan objek anonim dengan properti yang sesuai dengan nama kolom
Dalam praktiknya, Anda biasanya memerlukan tiga: FETCH_ASSOC, FETCH_CLASS, dan FETCH_OBJ. Untuk menentukan format data, gunakan sintaks berikut:
$STH->setFetchMode(PDO::FETCH_ASSOC);
Anda juga dapat mengaturnya secara langsung saat memanggil metode ->fetch().

FETCH_ASSOC

Format ini membuat array asosiatif dengan nama kolom sebagai indeks. Ini pasti familiar bagi mereka yang menggunakan ekstensi mysql/mysqli.
# karena ini adalah query biasa tanpa placeholder, # Anda dapat langsung menggunakan metode query() $STH = $DBH->query("SELECT name, addr, city from folks"); # mengatur mode pengambilan $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["name"] . "\n"; echo $row["addr"] . "\n"; echo $row["city"] . "\N" ;
Perulangan while() akan mengulangi seluruh hasil kueri.

FETCH_OBJ

Jenis akuisisi data ini membuat turunan kelas std untuk setiap baris.
# membuat kueri $STH = $DBH->query("PILIH nama, alamat, kota dari orang"); # pilih mode pengambilan $STH->setFetchMode(PDO::FETCH_OBJ); # cetak hasilnya while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . " \ N"; )

FETCH_CLASS

Saat menggunakan ambil_kelas, data ditulis ke instance kelas yang ditentukan. Dalam hal ini, nilai ditetapkan ke properti objek SEBELUM memanggil konstruktor. Jika properti dengan nama yang sesuai dengan nama kolom tidak ada, properti tersebut akan dibuat secara otomatis (dengan cakupan publik).

Jika data Anda memerlukan pemrosesan wajib segera setelah diterima dari database, data tersebut dapat diimplementasikan di konstruktor kelas.

Sebagai contoh, mari kita ambil situasi di mana Anda perlu menyembunyikan sebagian alamat tempat tinggal seseorang.
kelas secret_person ( public $name; public $addr; public $city; public $other_data; function __construct($other = "") ( $this->addr = preg_replace("//", "x", $this-> addr); $ini->data_lainnya = $lainnya;
Saat membuat objek, semua huruf latin kecil harus diganti dengan x. Mari kita periksa:
$STH = $DBH->query("PILIH nama, alamat, kota dari orang"); $STH->setFetchMode(PDO::FETCH_CLASS, "orang_rahasia"); while($obj = $STH->fetch()) ( echo $obj->addr; )
Jika alamat di database terlihat seperti '5 Rosebud', maka outputnya adalah '5 Rxxxxxx'.

Tentu saja, terkadang Anda ingin konstruktor dipanggil SEBELUM memberikan nilai. PDO juga mengizinkan hal ini.
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "secret_person");
Sekarang Anda telah melengkapi contoh sebelumnya dengan opsi tambahan (PDO::FETCH_PROPS_LATE), alamat tidak akan diubah, karena tidak ada yang terjadi setelah nilai ditulis.

Terakhir, jika perlu, Anda bisa meneruskan argumen ke konstruktor secara langsung saat membuat objek:
$STH->setFetchMode(PDO::FETCH_CLASS, "orang_rahasia", array("barang"));
Anda bahkan dapat memberikan argumen berbeda ke setiap objek:
$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // lakukan sesuatu $i++; )

Metode Berguna Lainnya

Meskipun artikel ini tidak dapat (dan tidak berusaha) mencakup setiap aspek bekerja dengan PDO (ini adalah modul yang sangat besar!), beberapa fitur berikut tidak dapat diabaikan begitu saja.
$DBH->lastInsertId();
Metode ->lastInsertId() mengembalikan id dari catatan yang terakhir dimasukkan. Perlu dicatat bahwa ini selalu dipanggil pada objek database (disebut $DBH dalam artikel ini), dan bukan pada objek dengan ekspresi ($STH).
$DBH->exec("HAPUS DARI orang DI MANA 1"); $DBH->exec("SET zona_waktu = "-8:00"");
Metode ->exec() digunakan untuk operasi yang tidak mengembalikan data apa pun selain jumlah catatan yang terpengaruh olehnya.
$aman = $DBH->quote($tidak aman);
Metode ->quote() menempatkan tanda kutip dalam data string sehingga aman untuk digunakan dalam kueri. Berguna jika Anda tidak menggunakan pernyataan yang sudah disiapkan.
$rows_affected = $STH->rowCount();
Metode ->rowCount() mengembalikan jumlah catatan yang berpartisipasi dalam operasi. Sayangnya, fungsi ini tidak berfungsi dengan kueri SELECT hingga PHP 5.1.6. Jika tidak memungkinkan untuk mengupdate versi PHP, jumlah record yang bisa didapat seperti ini:
$sql = "PILIH JUMLAH(*) DARI orang"; if ($STH = $DBH->query($sql)) ( # periksa jumlah record if ($STH->fetchColumn() > 0) ( # lakukan seleksi lengkap di sini karena data sudah ditemukan! ) else ( # cetak pesan bahwa tidak ditemukan data yang memenuhi permintaan) )

Kesimpulan

Saya harap materi ini dapat membantu sebagian dari Anda bermigrasi dari ekstensi mysql dan mysqli.