Arsip mwmag[Files]  [Up]© 2002 PT Masterweb Media

Pemrograman Berorientasi Objek pada PHP4

Apa Itu OOP?

Kelas dan Objek

Inheritance dengan extends

Polimorfisme

Kelas MySQLDb dan PostgreSQLDb

Contoh Aplikasi

Penutup

Rujukan

Daftar gambar

  1. Hasil tampilan menggunakan class MySQLDb
  2. Hasil tampilan menggunakan class PostgreSQLDb
Pemrograman Berorientasi Objek pada PHP4

Eko Bono Suprijadi dan Tedi Heriyanto

Artikel ini membahas apa itu sebenarnya OOP dalam konteks bahasa PHP4 dan bagaimana cara mengimplementasikannya dalam bentuk kelas dengan PHP4. Dilengkapi sebuah contoh nyata yang mengimplementasikan interface ke database MySQL dan PostgreSQL menggunakan kelas.

Jika kita bandingkan dengan PHP3, maka PHP4 mengalami perubahan yang mendasar. Engine skrip PHP, disebut juga Zend Engine, didesain ulang memakai paradigma kompilasi-lalu-eksekusi yang lebih efisien dibandingkan model eksekusi-sambil-parsing yang masih dipakai di PHP3. Selain itu PHP4 juga melakukan perbaikan fungsionalitas dan penyediaan fitur baru untuk pemrograman berorientasi objek maupun pembuatan kelas beserta objeknya, seperti misalnya pada pemanggilan konstruktor, pembuatan kelas turunan dan sebagainya.

Hal di atas cukup memberi alasan untuk mengupas secara rinci konsep OOP yang dipakai pada PHP4.

Apa Itu OOP?

Pemrograman Berorientasi Objek (OOP) tidak selalu mempunyai kesepakatan konsep yang sama dari satu bahasa komputer ke bahasa komputer lainnya. Namun ada tiga hal penting yang harus dipunyai oleh sebuah bahasa komputer untuk dapat disebut mendukung OOP:

Dari sini jelas bahwa PHP4 belum dapat dikategorikan sebagai bahasa yang mendukung OOP. Persyaratan enkapsulasi tidak dapat sepenuhnya diimplementasikan oleh PHP4, yang pada bahasa C++ atau Java direalisasikan dengan kata kunci private maupun protected. Pada PHP setiap atribut maupun metode masih dapat diakses langsung baik dari dari dalam kelas turunan, dari dalam kelas lainnya, maupun secara global.

Walaupun PHP4 tidak mengenal kata kunci abstract dan virtual seperti pada C++ maupun interface seperti pada Java, namun dukungan polimorfisme di PHP4 sudah diimplementasikan dengan cukup baik.

Faktor kekurangan lain seperti tidak adanya dukungan overloading metode (bukan overriding), tidak mengurangi pengguna PHP untuk menggunakan OOP dalam menulis program Web mereka, karena banyak faktor keuntungan yang dapat diperoleh seperti:

Kelas dan Objek

Dalam konteks PHP, kelas dapat dibayangkan sebagai kumpulan dari variabel dan fungsi yang akan menangani variabel tersebut. Kelas juga dapat dipandang sebagai bentuk proses enkapsulasi, walau tidak sepenuhnya kriteria ini terpenuhi seperti yang telah diutarakan sebelumnya.

Dalam contoh aplikasi nanti, kita akan mengambil tema koneksi ke database MySQL dan PostgreSQL yang direalisasikan dalam bentuk OOP. Kelas MySQLDb dipakai sebagai kelas dasar yang akan digunakan oleh kelas PostgreSQL sebagai kelas turunan. Namun agar lebih mudah dimengerti, pada pembahasan awal kita akan menggunakan kelas sederhana yang tidak berhubungan dengan kedua kelas tadi.

Berikut ini adalah contoh penulisan sebuah kelas A:

class A {
// Pendeklarasian variabel
var $host_1;

// Konstruktor
function A() {
...
}

// Definisi metode MetodeB
function MetodeB($args="") {
...
}
}

Variabel Anggota

Variabel anggota (member variable) dideklarasikan dengan menggunakan kata kunci var diikuti dengan nama variabel. Namun penggunaan variabel anggota ini tanpa pendeklarasian sebelumnya tidak akan menyebabkan kesalahan pada PHP4. Variabel ini hanya boleh diinisialisasi dengan konstanta. Penginisialisasian dengan non-konstanta harus dilakukan di dalam konstruktor. Dalam OOP, terminologi lain untuk variabel anggota adalah properti atau atribut.

// Global variabel
$gHost = "172.20.172.10";

// Class
class A {
// Benar, inisialisasi dengan konstanta
var $host_1="localhost";
// Deklarasi variabel host_2
var $host_2;

// Konstruktor
function A() {
global $gHost;

// Benar, inisialisasi dengan non-konstanta
$this->host_2=$gHost;

// Benar, definisi variabel baru dari class
$this->host_3="192.168.0.0";
}
}

Tentang Metode

Cara mendefinisikan sebuah metode sama seperti pada fungsi. Hanya saja, proses ini harus dilakukan dalam lingkup kelas yang bersangkutan. Metode MetodeB() adalah salah satu metode yang didefinisikan pada kelas A.

Pada PHP4 tidak dikenal istilah overloading metode, yaitu pendefinisian beberapa metode berbeda yang mempunyai nama sama namun memiliki daftar argumen yang berbeda. Dalam PHP4 setiap metode harus memiliki nama berbeda. Walau begitu, PHP4 mengenal terminologi argumen default untuk fungsi atau metode. Di sini jumlah dan tipe data dari argumen yang digunakan pada pemanggilan metode dapat berbeda.

...
class A {
...
// Metode B
function MetodeB($args="") {
...
}
}
...

Metode MetodeB() mempunyai argumen default string kosong jika dipanggil tanpa argumen. Dua kemungkinan untuk memanggil metode ini dengan benar adalah sebagai berikut:

ObjekA = new A;
ObjekA->MetodeB();

atau

ObjekA->MetodeB("localhost");

Pada penulisan program memakai gaya OOP, sangat disarankan untuk tidak mengakses atribut secara langsung, melainkan melalui metode. Di sini umumnya dipakai awalan Set untuk memberikan nilai yang baru sebuah variabel. Sedang untuk mengakses nilai atribut digunakan awalan Get.

function SetHost($host) {
$this->host_1 = $host;
}

function GetHost() {
return $this->host_1;
}

Cara ini berhubungan erat dengan prinsip enkapsulasi, yang pada PHP4 belum didukung sepenuhnya, sehingga secara tidak langsung menghilangkan keuntungan cara penulisan metode seperti di atas, karena tidak ada cara untuk melindungi atribut dari pengaksesan secara langsung.

Konstruktor dan Destruktor

PHP4 juga mengenal konstruktor yang dideklarasikan dengan memakai metode yang memiliki nama sama dengan nama kelas yang mendefinisikannya. Konstruktor ini akan dipanggil pada pembuatan sebuah objek dari kelas yang bersangkutan. Ada sedikit perbedaan antara PHP3 dan PHP4 dalam proses pemanggilan konstruktor—terutama pada kelas turunan—yang akan diterangkan di bagian akhir artikel.

Dalam contoh sebelumnya, metode A() adalah konstruktor dari kelas A. Di sini biasanya dilakukan inisialisasi terhadap variabel dengan nilai non-konstanta.

PHP tidak mengenal destruktor. Jika memang diinginkan, dapat digunakan fungsi PHP register_shutdown_function() yang akan dipanggil jika skrip PHP selesai dikerjakan.

Pembuatan Objek

Untuk dapat menggunakan kelas yang telah didefinisikan, kita perlu membuat instan dari kelas tersebut. Proses ini dapat dilakukan dengan bantuan operator new yang akan menghasilkan sebuah objek dari kelas bersangkutan. Dengan operator ini kita dapat membuat beberapa objek dari kelas yang sama. Karena objek adalah individu kelas, maka objek ini tidak mempunyai ketergantungan terhadap objek yang lain.

Setelah kita mempunyai sebuah objek, maka kita dapat mengakses variabel anggota maupun metode yang dimiliki kelas tersebut dengan bantuan operator ->.

// Pembuatan objek baru
ObjekA = new A;

// Pemanggilan metode MetodeB
ObjekA->MetodeB();

Cara Pengaksesan

Pengaksesan ke metode atau ke variabel di dalam lingkup kelas itu sendiri dilakukan dengan bantuan operator $this->. Sebagai contoh, untuk mengubah variabel $host_1 dalam metode MetodeB(), dapat dilakukan dengan $this->host_1 = "localhost".

Inheritance dengan extends

Seperti telah disinggung sebelumnya, inheritance adalah proses pembuatan sebuah kelas yang diturunkan dari kelas lain yang sudah didefinisikan sebelumnya. Salah satu faktor keuntungannya adalah, kita hanya tinggal menambahkan atribut atau metode yang dibutuhkan dalam kelas baru yang akan kita buat. Terminologi kelas yang dijadikan dasar pembuatan kelas baru ini adalah kelas dasar (base class) atau kelas induk (parent class). Sedang kelas yang baru disebut juga kelas turunan (extended class) atau kelas anak (child class).

Pembuatan kelas turunan di PHP4 dapat dilakukan dengan operator extends. Namun harus diingat bahwa dalam PHP4 hanya diperbolehkan menggunakan satu kelas dasar. Penurunan dari beberapa kelas (multiple inheritance) tidak diperbolehkan.

Hal yang juga penting di sini adalah pemanggilan konstruktor kelas turunan. Pada PHP4, jika konstruktor kelas turunan tidak didefinisikan, maka otomatis konstruktor kelas dasar yang akan dipanggil, jika ada. Sedangkan pada PHP3, jika konstruktor kelas turunan tidak ada, konstruktor kelas dasar tidak akan dipanggil.

Berikut ini ilustrasi cara pembuatan kelas turunan dan pemanggilan konstruktor:

// Kelas dasar
class A {
function A() {
echo "Konstruktor class A.<br>\n";
}
}

// Kelas turunan
class B extends A {
}

$ObjekB = new B;

Kelas B yang tidak mempunyai konstruktor diturunkan dari kelas A yang mempunyai konstruktor. Seperti diharapkan, pada pembuatan objek dari kelas B, maka konstruktor kelas A akan dipanggil. Program di atas akan menampilkan keluaran:

Konstruktor kelas A.

Dalam manual PHP4 dikatakan, jika kelas turunan tidak mempunyai konstruktor, maka konstruktor dari kelas dasar, yaitu metode yang mempunyai nama sama dengan nama kelas dasar, akan dipanggil. Namun pada PHP versi 4.0.4 maupun 4.0.5 hal ini belum dilakukan. Kita akan melihat kasus berikut.

Sekarang jika kita menambahkan sebuah metode di kelas A dengan nama B() (sengaja namanya sama dengan nama kelas B), dan kita jalankan lagi program di atas, maka yang keluar tidak seperti yang kita harapkan.

class A {
...
// Metode tambahan
function B() {
echo "Metode normal B.<br>\n";
}
}

Tampilan yang dikeluarkan adalah seperti berikut:

Metode normal B.

Di sini tiba-tiba metode B() di kelas A menjadi konstruktor dari kelas B yang akan dipanggil secara otomatis pada setiap pembuatan objek baru dari kelas A. Hal ini seharusnya hanya ditemui pada PHP3, dan tidak pada PHP4 seperti informasi di manual. Kemungkinan besar versi yang sekarang ada masih mengandung kesalahan.

Kelas turunan dapat melakukan overriding metode dari kelas dasar. Jika metode di kelas dasar yang sudah dioverride ini hendak dipanggil dari kelas turunan, maka dapat digunakan operator ::. Operator ini juga dapat dipakai dari lingkup global untuk memanggil metode dari suatu kelas tanpa membuat objek terlebih dahulu.

class A {
function hallo() {
echo "Metode hallo dari class A.<br>\n";
}
}

class B extends A {
// Override metode hallo dari class A
function hallo() {
echo "Metode hallo dari class B.<br>\n";
// Memanggil metode hallo di class A
A::hallo(); // Atau dapat juga parent::hallo()
}
}

// Memanggil metode tanpa objek
A::hallo();

$ObjekB = new B;
$ObjekB->hallo();

Program di atas akan menampilkan keluaran seperti berikut:

Metode hallo dari class A.
Metode hallo dari class B.
Metode hallo dari class A.

Untuk mengakses variabel anggota atau metode di kelas dasar tanpa harus tahu nama kelasnya, dapat digunakan kata kunci parent. Pada contoh di atas, jika baris A::hallo() diganti dengan parent::hallo() maka hasilnya akan identik.

Polimorfisme

Seperti dituliskan sebelumnya, polimorfisme adalah cara yang memungkinkan pengaksesan ke suatu metode bergantung dari tipe data objek yang diakses, termasuk dari metode di kelas dasar. Untuk memperjelasnya, mari kita lihat contoh berikut. Di sini kita akan membuat satu kelas dasar, Bangun2D dan dua kelas turunan, Lingkaran dan PersegiPanjang.

class Bangun2D {
function Luas() {}
function Keliling() {}
function Info() {
echo "Luas = ", $this->Luas(), ", Keliling = ", $this->Keliling();
echo “<br>\n";
}
}

class Lingkaran extends Bangun2D {
var $r;
function Lingkaran($r) { $this->r = $r; }
function Luas() { return pi()*$this->r*$this->r; }
function Keliling() { return 2*pi()*$this->r; }
}

class PersegiPanjang extends Bangun2D {
var $p;
var $l;
function PersegiPanjang($p, $l) { $this->p = $p; $this->l = $l; }
function Luas() { return $this->p*$this->l; }
function Keliling() { return 2*($this->p+$this->l); }
}

$bangun[] = new Lingkaran(10);
$bangun[] = new PersegiPanjang(6, 8);

foreach ($bangun as $b) {
$b->Info();
}

Program di atas akan menampilkan keluaran seperti berikut:

Luas = 314.15926535898, Keliling = 62.831853071796
Luas = 48, Keliling = 28

Dari contoh ini dapat dilihat, metode Info() kelas dasar Bangun2D tidak perlu mengetahui di kelas turunan mana ia sedang berada untuk mengetahui bagaimana cara menghitung luas dan keliling bangun. Jika metode ini dipanggil dari sebuah objek persegipanjang, maka Luas() dan Keliling() dari kelas Persegipanjang yang akan dipanggil; jika objek sebuah lingkaran, maka luas dan keliling lingkaran yang dihitung. Keuntungannya, jika suatu saat kita menambah bangun khusus lain, katakanlah Segitiga atau Poligon, maka metode Info() kelas Bangun2D tidak perlu diubah. Dengan kata lain, metode Info() menjadi reusable. Atau, bisa dikatakan juga bahwa OO dan polimorfisme mengizinkan kode lama (kelas Bangun2D) dapat memanggil kode baru (kelas Segitiga atau Poligon di masa depan).

Kelas MySQLDb dan PostgreSQLDb

Setelah kita belajar teori Pemrograman Berorientasi Objek dengan PHP, maka kita akan melihat penggunaannya dalam aplikasi yang nyata. Dalam CD majalah Anda akan menemukan file oop_php.tgz. Di dalamnya berisi antara lain file mysql.class.php yang mengimplementasikan kelas MySQLDb dan psql.class.php yang mengimplementasikan kelas PostgreSQLDb.

Kelas MySQLDb adalah kelas dasar yang mempunyai metode untuk melakukan operasi ke server database MySQL dengan instruksi sesederhana mungkin dalam pekerjaan yang kompleks. Sebuah objek dari kelas ini dapat melakukan operasi berulang kali, tanpa kehilangan informasi atau data dari operasi sebelumnya. Hal ini sangat bermanfaat terutama ketika melakukan query select.

Kelas PostgreSQLDb sebagai kelas turunan mempunyai fitur yang sama dengan kelas induknya MySQLDb.

Hubungan antara kedua kelas dalam contoh kita kali ini barangkali bukan teladan model abstraksi yang optimal. Dalam aplikasi abstraksi database yang lebih umum, biasanya dibuat satu kelas dasar abstrak yang mendefinisikan interface yang seragam, lalu dibuat kelas-kelas turunan sebagai driver untuk masing-masing jenis database. Jadi biasanya kelas MySQL dan PostgreSQL letaknya sederajat satu sama lain, di bawah satu kelas induk. Contohnya adalah di Perl dengan DBI sebagai kelas induk dan DBD::mysql serta DBD::Pg sebagai kelas-kelas driver. Namun demi kesederhanaan contoh, kita hanya akan membuat dua kelas seperti telah disebutkan sebelumnya.

Konstruktor MySQLDb

Kebanyakan aplikasi PHP mempunyai sebuah file konfigurasi yang berisikan banyak variabel global yang dibutuhkan oleh file lainnya. Pengguna aplikasi biasanya cukup mengedit file ini untuk menyesuaikan aplikasi di sistem yang ada.

Demikian juga kelas MySQLDb dapat dikonfigurasi baik lewat daftar argumen maupun lewat variabel global di mana daftar argumen mempunyai prioritas lebih tinggi. Proses konfigurasi ini dilakukan oleh konstruktor.

class MySQLDb {
...
function MySQLDb($args="") {
global $cfgDBHost, $cfgDBPort, $cfgDBUser, $cfgDBPasswd;

$this->dbh = false;

if (isset($args["host"]))
$this->host=$args["host"];
else
$this->host=$cfgDBHost;

if (isset($args["port"]))
$this->port=$args["port"];
else
$this->port=$cfgDBPort;

if (isset($args["user"]))
$this->user=$args["user"];
else
$this->user=$cfgDBUser;

if (isset($args["passwd"]))
$this->passwd=$args["passwd"];
else
$this->passwd=$cfgDBPasswd;

$this->rownr=0;
}

Metode Select()

Sebagian besar operasi ke database adalah query select. Metode Select() dalam kelas MySQLDb yang menangani operasi ini diimplementasikan sedemikian rupa, sehingga hasilnya disimpan dalam sebuah array yang sekaligus digunakan sebagai nilai kembali oleh metode ini. Dengan demikian data hasil query dapat diakses langsung tanpa harus melewati objek lagi.

  function Select($string) {
$this->rowcount=0;
$result = mysql_query($string, $this->dbh);
$this->error=mysql_error();
if (empty($this->error)){
$entry = array();
$this->rowcount=mysql_num_rows($result);
$i=0;
while($row=mysql_fetch_array($result)){
$entry[$i] = $row;
$i++;
}
mysql_free_result($result);
}
return $entry;
}

Kelas PostgreSQLDb

Kelas PostgreSQLDb diturunkan dari kelas MySQLDb. Karena proses pengkonfigurasian sama seperti pada MySQL, maka konstruktor kelas ini hanya memanggil konstruktor dari base kelasnya.

class PostgreSQLDb extends MySQLDb {

function PstgreSQLDb($args="") {
parent::MySQLDb($args);
}
...
}

Jika kelas PostgreSQLDb ini tidak diturunkan dari kelas MySQLDb maka kita harus menulis lagi konstruktor yang sama seperti pada konstruktor MySQLDb.

Untuk mengetahui metode lainnya, pembaca dapat melihat langsung source code dari kedua kelas tersebut.

Contoh Aplikasi

Di sini akan diberikan satu aplikasi sederhana yang melakukan query ke database MySQL atau PostgreSQL, dan menampilkan hasilnya ke browser. Variabel yang diperlukan dalam proses koneksi ke server database disimpan dalam file konfigurasi config.inc.php yang akan digunakan oleh konstruktor kelas dasar MySQLDb.

Setelah mengedit variabel global yang harus disesuaikan dengan sistem yang Anda pakai, maka untuk memilih kelas mana yang akan digunakan, pengguna cukup menuliskan nama kelas yang dilewatkan sebagai parameter fungsi page_open() yang diimplementasi dalam file page.inc.php.

// Menggunakan kelas MySQLDb
if (!page_open(array("db" => 1,
"dbkelas" => "MySQLDb",
"page" => $PHP_SELF)))
die;

Jika ingin menggunakan kelas PostgreSQLDb maka Anda tinggal mengganti parameter "dbkelas"=>"MySQLDb" dengan "dbkelas"=>"PostgreSQLDb".

Pembuatan objek dari kelas sendiri akan ditangani oleh fungsi page_open(). Pada PHP hal ini dimungkinkan karena kelas juga dapat disimpan dalam variabel seperti kita lihat di bawah ini:

  function page_open($args) {
global $cfgDatabase,$gDb;

// Menggunakan database ?
if (isset($args["db"])){
// Kelas database ada di argumen?
if (isset($args["dbclass"]))
$gDb = new $args["dbclass"];
// Memakai default
else
$gDb = new MySQLDb;

return $gDb->Connect();
}
return true;
}

Variabel global $gDb adalah objek kelas yang namanya tersimpan dalam $args["dbkelas"].

Dalam CD ada dua jenis file yang digunakan sebagai contoh aplikasi, yaitu mysql.php yang menggunakan kelas MySQLDb dan file postgres.php yang menggunakan kelas PostgreSQLDb untuk mengambil entri data dari tabel users. Gambar 1 dan 2 menunjukkan hasil tampilan keduanya.

Penutup

Masih banyak tema yang tidak dapat dituliskan di sini seperti serialisasi dan referensi pada objek dari kelas. Namun para penulis berharap artikel ini dapat memberikan dasar untuk lebih mudah mempelajari tema lanjutan tentang OOP dengan PHP. Akhir kata, selamat mencoba.

Rujukan

Notasi [cd] berarti terdapat di CD majalah.

  1. PHP Manual [cd]
  2. C++ Annotations Version 4.4.2, Frank B. Brokken, 2000

Eko Bono Suprijadi programer hobiis, dapat dihubungi di ekobono@hotmail.com. Tedi Heriyanto seorang programer software bebas, dapat dihubungi di tedi_h@gmx.net.

mw

Arsip mwmag[Files]  [Up]www.master.web.id/mwmag