Penggunaan fungsi GETCONNECTION pada PHP

Indonesian (Bahasa Indonesia) translation by Ari Ana (you can also view the original English article)

Banyak programmer PHP belajar cara mengakses database dengan menggunakan ekstensi MySQL atau MySQLi. Di PHP 5.1, ada cara yang lebih baik. PHP Data Objects (PDO) menyediakan metode untuk prepared statements dan bekerja dengan objek yang akan membuat Anda jauh lebih produktif!

Publikasi Ulang Tutorial

Setiap beberapa minggu, kami mengunjungi beberapa posting favorit pembaca kami dari seluruh sejarah situs ini. Tutorial ini pertama kali dipublikasikan pada bulan Mei tahun 2010.


Pendahuluan PDO

"PDO - PHP Data Objects - adalah lapisan akses database yang menyediakan metode akses yang seragam ke beberapa database."

Ini tidak memperhitungkan sintaks database-spesifik, namun memungkinkan proses peralihan database dan platform menjadi lebih mudah, cukup dengan mengganti string koneksi dalam banyak instance.

Penggunaan fungsi GETCONNECTION pada PHP

Tutorial ini tidak dimaksudkan untuk menjadi petunjuk lengkap tentang SQL. Ini ditulis terutama untuk orang-orang yang saat ini menggunakan ekstensi mysql atau mysqli untuk membantu mereka membuat lompatan ke PDO yang lebih portabel dan canggih.

Dukungan Database

Ekstensi dapat mendukung database apapun yang disediakan oleh driver PDO. Pada saat penulisan ini, driver database berikut yang tersedia:

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

Semua driver ini belum tentu tersedia di sistem Anda; inilah cara cepat untuk mengetahui driver mana yang Anda miliki:

print_r(PDO::getAvailableDrivers());

Menghubungkan

Database yang berbeda mungkin memiliki metode koneksi yang sedikit berbeda. Di bawah ini, metode untuk terhubung ke beberapa database terpopuler akan ditampilkan. Anda akan melihat bahwa tiga yang pertama adalah identik, lainnya adalah jenis database - dan kemudian SQLite memiliki sintaksnya sendiri.

Penggunaan fungsi GETCONNECTION pada PHP

try {
  # MS SQL Server and Sybase with PDO_DBLIB
  $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass");
  $DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass");

  # MySQL with PDO_MYSQL
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

  # SQLite Database
  $DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
    echo $e->getMessage();
}

String KoneksiHarap perhatikan blok try/catch - Anda harus selalu membungkus operasi PDO Anda di dalam try/catch, dan gunakan mekanisme exception - lebih lanjut tentang ini segera. Biasanya Anda hanya akan membuat satu koneksi - ada beberapa yang terdaftar untuk menunjukkan sintaksnya. $DBH adalah singkatan dari 'database handle' dan akan digunakan sepanjang tutorial ini.

Anda dapat menutup koneksi dengan mengatur handle ke null.

# close the connection
$DBH = null;

Anda bisa mendapatkan lebih banyak informasi tentang opsi spesifik dan/atau string koneksi database untuk database lain dari PHP.net.


Exception dan PDO

PDO dapat menggunakan exception untuk menangani kesalahan, yang berarti apapun yang Anda lakukan dengan PDO harus dibungkus dalam blok try/catch. Anda dapat memaksa PDO ke salah satu dari tiga mode kesalahan dengan menetapkan atribut mode kesalahan pada handle database yang baru Anda buat. Inilah sintaksnya:

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

Tidak masalah mode kesalahan yang Anda tetapkan, kesalahan menghubungkan akan selalu menghasilkan exception, dan membuat koneksi harus selalu terkandung di blok try/catch.

PDO::ERRMODE_SILENT

Ini adalah mode kesalahan default. Jika Anda membiarkannya dalam mode ini, Anda harus memeriksa kesalahan dengan cara yang mungkin Anda gunakan jika Anda menggunakan ekstensi mysql atau mysqli. Dua metode lainnya lebih ideal untuk pemrograman DRY.

PDO::ERRMODE_WARNING

Mode ini akan mengeluarkan peringatan standar PHP, dan memungkinkan program melanjutkan eksekusi. Ini berguna untuk debugging.

PDO::ERRMODE_EXCEPTION

Ini adalah mode yang Anda inginkan dalam kebanyakan situasi. Ini menimbulkan exception, memungkinkan Anda menangani kesalahan dengan anggun dan menyembunyikan data yang mungkin bisa membantu seseorang mengeksploitasi sistem Anda. Inilah contoh untuk memanfaatkan exceptions:

# connect to the database
try {
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

  # UH-OH! Typed DELECT instead of SELECT!
  $DBH->prepare('DELECT name FROM people');
}
catch(PDOException $e) {
    echo "I'm sorry, Dave. I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

Ada kesalahan yang disengaja dalam pernyataan select; ini akan menyebabkan exception. Exception mengirimkan rincian kesalahan ke file log, dan menampilkan pesan yang ramah (atau tidak ramah) kepada pengguna.


Insert dan Update

Memasukkan data baru, atau memperbarui data yang ada adalah salah satu operasi database yang lebih umum. Dengan menggunakan PDO, ini biasanya merupakan proses dua langkah. Semua yang tercakup dalam bagian ini berlaku sama untuk operasi UPDATE dan INSERT.

Penggunaan fungsi GETCONNECTION pada PHP

Berikut adalah contoh jenis insert yang paling dasar:

# STH means "Statement Handle"
$STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
$STH->execute();

Anda juga bisa mencapai operasi yang sama dengan menggunakan metode exec(), dengan satu panggilan. Dalam kebanyakan situasi, Anda akan menggunakan metode yang lebih panjang sehingga Anda dapat memanfaatkan prepared statements. Bahkan jika Anda hanya akan menggunakannya sekali, dengan menggunakan prepared statements akan membantu melindungi Anda dari serangan injeksi SQL.

Prepared Statements

Menggunakan prepared statements akan membantu melindungi Anda dari injeksi SQL.

Prepared statement adalah pernyataan SQL yang telah dikompilasi awal yang dapat dijalankan beberapa kali dengan hanya mengirimkan data ke server. Ini memiliki keuntungan tambahan secara otomatis membuat data yang digunakan di placeholder aman dari serangan injeksi SQL.

Anda menggunakan prepared statement dengan memasukkan placeholder di SQL Anda. Inilah tiga contohnya: satu tanpa placeholder, satu dengan placeholder tanpa nama, dan satu dengan placeholder bernama.

# no placeholders - ripe for SQL Injection!
$STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");

# unnamed placeholders
$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);

# named placeholders
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");

Anda ingin menghindari metode pertama; itu di sini untuk perbandingan. Pilihan menggunakan placeholder bernama atau tidak bernama akan mempengaruhi bagaimana Anda mengatur data untuk pernyataan tersebut.

Placeholder Tak Bernama

# assign variables to each place holder, indexed 1-3
$STH->bindParam(1, $name);
$STH->bindParam(2, $addr);
$STH->bindParam(3, $city);

# insert one row
$name = "Daniel"
$addr = "1 Wicked Way";
$city = "Arlington Heights";
$STH->execute();

# insert another row with different values
$name = "Steve"
$addr = "5 Circle Drive";
$city = "Schaumburg";
$STH->execute();

Ada dua langkah di sini. Pertama, kita menugaskan variabel ke berbagai placeholder (baris 2-4). Kemudian, kita memberikan nilai kepada placeholder tersebut dan mengeksekusi pernyataan tersebut. Untuk mengirim kumpulan data lainnya, cukup ubah nilai variabel tersebut dan jalankan kembali pernyataan tersebut.

Apakah ini tampak agak berat untuk pernyataan dengan banyak parameter? Ya. Namun, jika data Anda disimpan dalam array, ada jalan pintas yang mudah:

# the data we want to insert
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');

$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
$STH->execute($data);

Itu mudah!

Data dalam array berlaku untuk placeholder secara berurutan. $data[0] masuk ke placeholder pertama, $data[1] yang kedua, dll. Namun, jika indeks array Anda tidak sesuai, ini tidak akan bekerja dengan baik, dan Anda perlu mengindeks ulang array.

Placeholder Bernama

Anda mungkin bisa menebak sintaksnya, tapi inilah contohnya:

# the first argument is the named placeholder name - notice named
# placeholders always start with a colon.
$STH->bindParam(':name', $name);

Anda juga bisa menggunakan singkatan di sini, tapi bekerja dengan array asosiatif. Inilah contohnya:

# the data we want to insert
$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );

# the shortcut!
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute($data);

Kunci array Anda tidak perlu dimulai dengan titik dua, tapi jika tidak perlu mencocokkan placeholder bernama. Jika Anda memiliki array dari array Anda dapat melakukan iterasi atas mereka, dan hanya memanggil execute dengan setiap array data.

Fitur bagus lainnya dari placeholder bernama adalah kemampuan untuk memasukkan objek secara langsung ke database Anda, dengan asumsi properti-propertinya sesuai dengan bidang yang dinamai. Inilah contoh objek, dan bagaimana Anda melakukan insert Anda:

# a simple object
class person {
    public $name;
    public $addr;
    public $city;

    function __construct($n,$a,$c) {
        $this->name = $n;
        $this->addr = $a;
        $this->city = $c;
    }
    # etc ...
}

$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');

# here's the fun part:
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);

Dengan melemparkan objek ke array dalam execute, properti diperlakukan sebagai kunci array.


Memilih Data

Penggunaan fungsi GETCONNECTION pada PHP

Mengambil data menjadi array atau objekData diperoleh melalui ->fetch(), sebuah metode dari handle pernyataan Anda. Sebelum memanggil fetch, yang terbaik adalah memberi tahu PDO bagaimana Anda ingin data diambil. Anda memiliki pilihan berikut:

  • PDO::FETCH_ASSOC: mengembalikan sebuah array yang diindeks dengan nama kolom
  • PDO::FETCH_BOTH (default): mengembalikan sebuah array yang diindeks dengan nama kolom dan nomor
  • PDO::FETCH_BOUND: Menetapkan nilai kolom Anda ke variabel yang ditetapkan dengan metode ->bindColumn()
  • PDO::FETCH_CLASS: Menetapkan nilai kolom Anda ke properti kelas bernama. Ini akan menciptakan properti jika properti yang cocok tidak ada
  • PDO::FETCH_INTO: Memperbarui instance kelas bernama
  • PDO::FETCH_LAZY: Menggabungkan PDO::FETCH_BOTH/PDO::FETCH_OBJ, membuat nama variabel objek saat digunakan
  • PDO::FETCH_NUM: mengembalikan sebuah array yang diindeks dengan nomor kolom
  • PDO::FETCH_OBJ: mengembalikan sebuah objek anonim dengan nama properti yang sesuai dengan nama kolom

Pada kenyataannya, ada tiga hal yang akan mencakup sebagian besar situasi: FETCH_ASSOC, FETCH_CLASS, dan FETCH_OBJ. Untuk mengatur metode fetch, sintaks berikut digunakan:

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

Anda juga dapat mengatur jenis fetch langsung di dalam panggilan metode ->fetch().

FETCH_ASSOC

Jenis fetch ini membuat array asosiatif, diindeks berdasarkan nama kolom. Ini harus cukup familiar bagi siapa saja yang telah menggunakan ekstensi mysql/mysqli. Berikut adalah contoh pemilihan data dengan metode ini:

# using the shortcut ->query() method here since there are no variable
# values in the select statement.
$STH = $DBH->query('SELECT name, addr, city from folks');

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_ASSOC);

while($row = $STH->fetch()) {
    echo $row['name'] . "\n";
    echo $row['addr'] . "\n";
    echo $row['city'] . "\n";
}

While loop akan terus melewati hasil set satu baris sekaligus sampai selesai.

FETCH_OBJ

Jenis fetch ini menciptakan objek kelas std untuk setiap baris data yang diambil. Inilah contohnya:

# creating the statement
$STH = $DBH->query('SELECT name, addr, city from folks');

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_OBJ);

# showing the results
while($row = $STH->fetch()) {
    echo $row->name . "\n";
    echo $row->addr . "\n";
    echo $row->city . "\n";
}

FETCH_CLASS

Properti objek Anda ditetapkan SEBELUM constructor dipanggil. Ini penting.

Metode fetch ini memungkinkan Anda untuk mengambil data secara langsung ke dalam kelas yang Anda pilih. Bila Anda menggunakan FETCH_CLASS, properti objek Anda ditetapkan SEBELUM constructor dipanggil. Baca lagi, ini penting. Jika properti yang cocok dengan nama kolom tidak ada, properti tersebut akan dibuat (sebagai public) untuk Anda.

Ini berarti jika data Anda memerlukan transformasi setelah keluar dari database, ini bisa dilakukan secara otomatis oleh objek Anda saat setiap objek dibuat.

Sebagai contoh, bayangkan sebuah situasi dimana alamat tersebut perlu dikaburkan sebagian untuk setiap record. Kita bisa melakukan ini dengan mengoperasikan properti itu di constructor. Inilah contohnya:

class secret_person {
    public $name;
    public $addr;
    public $city;
    public $other_data;

    function __construct($other = '') {
        $this->address = preg_replace('/[a-z]/', 'x', $this->address);
        $this->other_data = $other;
    }
}

Karena data diambil ke kelas ini, alamatnya memiliki semua huruf a-z huruf kecil diganti dengan huruf x. Sekarang, dengan menggunakan kelasnya dan mentransformasi data terjadi benar-benar transparan:

$STH = $DBH->query('SELECT name, addr, city from folks');
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person');

while($obj = $STH->fetch()) {
    echo $obj->addr;
}

Jika alamatnya adalah '5 Rosebud,' Anda akan melihat '5 Rxxxxxx' sebagai output Anda. Tentu saja, mungkin ada situasi di mana Anda ingin constructor dipanggil sebelum data diberikan. PDO telah membantu Anda untuk ini juga.

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

Sekarang, ketika Anda mengulangi contoh sebelumnya dengan mode fetch ini (PDO::FETCH_PROPS_LATE), alamat TIDAK akan dikaburkan, karena constructor sudah dipanggil dan propertinya ditetapkan.

Akhirnya, jika Anda benar-benar perlu, Anda bisa menyampaikan argumen kepada constructor saat mengambil data ke objek dengan PDO:

$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));

Jika Anda perlu mengirimkan data yang berbeda ke constructor untuk setiap objek, Anda dapat mengatur mode fetch di dalam metode fetch:

$i = 0;
while($rowObj =  $STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) {
    // do stuff
    $i++
}

Beberapa Metode Bermanfaat Lainnya

Meskipun ini tidak dimaksudkan untuk mencakup semuanya di PDO (ini adalah ekstensi yang sangat besar!) ada beberapa metode lagi yang ingin Anda ketahui untuk melakukan hal mendasar dengan PDO.

$DBH->lastInsertId();

Metode ->lastInsertId() selalu dipanggil pada handle database, bukan handle pernyataan, dan akan mengembalikan id auto increment dari baris yang dimasukkan terakhir oleh koneksi itu.

$DBH->exec('DELETE FROM folks WHERE 1');
$DBH->exec("SET time_zone = '-8:00'");

Metode ->exec() digunakan untuk operasi yang tidak dapat mengembalikan data selain dari affected rows. Berikut adalah dua contoh penggunaan metode exec.

$safe = $DBH->quote($unsafe);

Metode ->quote() mengutip string sehingga mereka aman digunakan dalam query. Ini adalah fallback Anda jika Anda tidak menggunakan prepared statements.

$rows_affected = $STH->rowCount();

Metode  ->rowCount() mengembalikan integer yang menunjukkan jumlah baris yang terpengaruh oleh sebuah operasi. Paling tidak satu versi PDO yang diketahui, menurut [laporan bug ini](http://bugs.php.net/40822) metode ini tidak bekerja dengan pernyataan select. Jika Anda mengalami masalah ini, dan tidak bisa mengupgrade PHP, Anda bisa mendapatkan jumlah baris dengan yang berikut ini:

$sql = "SELECT COUNT(*) FROM folks";
if ($STH = $DBH->query($sql)) {
    # check the row count
    if ($STH->fetchColumn() > 0) {

    # issue a real select here, because there's data!
    }
    else {
        echo "No rows matched the query.";
    }
}

Kesimpulan

Saya harap ini membantu beberapa dari Anda bermigrasi dari ekstensi mysql dan mysqli. Apa yang Anda pikirkan? Apakah ada di antara Anda yang mungkin beralih?