Sunday, December 7, 2008

Pengecualian di PHP 5

Beberapa waktu lalu di milist id-php ada yang sempat bertanya tentang Exception di PHP 5. Beberapa contoh yang diberikan, menurut gue masih kurang menunjukkan kemampuan dari exception itu sendiri, maka dari itu gue mencoba untuk ikutan memberikan jawaban dan contoh.

Tulisan gue di milist, gue coba tulis kembali di blog gue, untuk sekedar jadi arsip gue. Mungkin juga bisa membantu yang lain apabila ada yang cari-cari informasi tentang exception di PHP 5. Beberapa dari contoh yang gue kasih di tulisan gue waktu itu gue perbaiki karena ada kesalahan di syntaxnya. Apabila masih ada yang perlu di koreksi atau kritik dan saran, gue terima dengan senang hati.

Secara umum penggunaan exception bisa dibaca di dokumentasi PHP 5. Beberapa dari contoh yang disebutkan di milist, menunjukkan bahwa exception dapat digunakan untuk melihat backtrace error. Memang benar dengan exception kita bisa melihat backtrace error dari programmnya. Tapi untuk backtrace sendiri PHP sebenarnya sudah punya debug_backtrace.

Bukan berarti kita tidak boleh menggunakan Exception untuk melakukan backtrace. Tentu saja boleh, malah kalau kita bekerja menggunakan orientasi obyek, kita justru dipermudah dalam hal backtrace menggunakan Exception. Akan tetapi gue pengen kasih contoh tujuan yang sebenarnya dari exception itu sendiri.

Sebelum itu gue mau mencoba mengutip satu contoh yang diberikan di milist dalam thread ini.
<?php
if (!is_writable($this->file)) {
    throw new Exception("file '{$file}' is not writeable");
}
file_put_contents($file,$xmlObj->asXML());

//apa bedanya klo saya buat seperti ini ? :
if (!is_writable($this->file)) {
    echo "Aduuwwhhh filenya ndak bisa ditulisi!";
    exit();
}
file_put_contents($file,$xmlObj->asXML());`
?>
Contoh tersebut membuat PHP mengeluarkan error message "uncaught exception". Ini sebenarnya sebuah error yang tidak boleh ada. Kalau di java, hal seperti ini membuat code java nya sendiri gak bisa di compile, sampai sang programmer membuat try-catch block pada programm code yang berpotensi untuk melempar exception tersebut.

Seperti yang gue bilang diatas, kita bisa menggunakan exception, sebagai error handler, tapi bukan berarti exception itu melulu merupakan sebuah "error". Dengan exception kita diberi kesempatan untuk melakukan sesuatu (handle) terhadap exception tersebut.

Gue akan memberikan contoh yang mengacu pada contoh diatas. Dan gue coba berikan sebuah skenario dimana penggunaan exception bisa digunakan.

  • Gue harus membuat sebuah methode (dalam class) yang dapat menulis xml kedalam sebuah file.
  • Untuk menulis file kedalam xml, maka gue butuh 2 parameter, yaitu file, dan string.
  • Parameter file tersebut harus sebuah file resource, harus bisa dibaca dan harus bisa ditulis.
  • Parameter string tersebut harus sebuah string, dan merupakan xml yang conform.
  • Apabila semua prosedur itu dipenuhi maka xml tersebut bisa ditulis kedalam file.
Berikut adalah contoh kelasnya.
<?php
class PutXMLToFile{

   public function putThatThing($file, $xml){
        if(!is_file($file)){
           throw new ExceptionIsNotAFile('Resource is not a File!');
        }

        if(!is_readable($file)){
           throw new ExceptionFileNotReadable('File not readable.');
        }

        if(!is_writeable($file)){
           throw new ExceptionFileNotWriteable('File not writeable');
        }

        if(!is_string($string)){
           throw new ExceptionIsNotAString('not a string');
        }

        if(!is_xml_conform($string)){
           throw new ExceptionIsNotXMLConform('not xml conform');
        }

        file_put_contents($file,$string);
   }
}
?>
Dengan ini kita akan memberikan code ini - misalnya - kepada kolega kerja kita, yang bertanggung jawab untuk user interface. Katakanlah ada 2 kolega kita yang bertanggung jawab untuk UI, yang satu UI untuk browser biasa, yang satu UI untuk mobile browser.

Requirementnya sebagai berikut.
  • Apabila file, bukan sebuah file, maka buka UI file management untuk memilih atau mengupload file.
  • Apabila file tidak dapat dibaca, atau tidak dapat ditulis, maka buka UI file access management untuk mengedit file access.
  • Apabila string bukan string, tampilkan error message.
  • Apabila string tidak xml conform, maka tampilkan UI xml editor untuk mengedit xml file tersebut.
Sekarang gue bukin contoh untuk UI mobile browser. Gue anggap user interface object nya sudah jadi saja.
<?php
$userInterface = new MobileUserInterface();

try{
   $putXMLToFile = new PutXMLToFile();
   $putXMLToFile->putThatThing($file, $string);
}catch (ExceptionIsNotAFile $e){
    $userInterface->openFileManager();
}catch (ExceptionFileNotReadable $e){
     $userInterface->openFileAccessManager();
}catch (ExceptionFileNotWriteable $e){
     $userInterface->openFileAccessManager();
}catch (ExceptionIsNotAString $e){
     $userInterface->showError($e->getMessage());
}catch (ExceptionIsNotXMLConform $e){
     $userInterface->openXMLEditor();
}
?>
Seperti yang bisa kita lihat, fungsi pada contoh pertama untuk put xml to file jadi lebih loose coupled dan mudah diimplementasikan di berbagai macam kebutuhan. Kolega kita yang ingin mengerjakan UI untuk browser biasa misalnya bisa melakukan seperti code diatas, hanya saja object nya bukan new MobileUserInterface() tapi new StandardUserInterface() misalnya.

Dalam try{} block kolega kita juga bisa untuk tidak hanya menulis code yang akan menangkap exception dari object kita, tapi juga dari object lain. Dalam arti di dalam try{} block bisa terjadi algoritma yang cukup komplex.

Misalnya saja requierement yang diatas ditambahkan lagi:
  • Setelah berhasil put xml to string, maka save informasi tersebut ke dalam database,
  • lalu kirimkan email kepada orang yang bersangkutan.
Database object dan email object, bisa jadi memiliki exception mereka sendiri yang sudah selayaknya ditangkap entah itu connection not avaliable, column or table not exist, database not exist, sql statement syntax error dan sejenisnya.

Pada email object bisa jadi, mail server not responding, atau email address invalid atau email address not exist in database, dan sejenisnya.

Exception tersebut juga bisa ditangkap dan dilakukan sesuatu(handle) terhadap exception tersebut. Bisa jadi hanya menampilkan error. Tapi seperti contoh di atas, tidak selalu exception itu merupakan sebuah error. Berikut adalah contoh pengembangan code yang diatas:
<?php
$db = DBObject::getInstance();

try{
   $putXMLToFile = new PutXMLToFile();
   $putXMLToFile->putThatThing($file, $string);

   $db->beginTransaction();
   $modelSomething->insertSomething();
   $modelAnything->updateAnything();

   $email = Email::getInstance();
   $email->setTo($emailAddressTo);
   $email->setSubject($emailSubject);
   $email->setMessage(emailMessage);
   $email->send();

   $db->endTransaction();

}catch (ExceptionIsNotAFile $e){
    $userInterface->openFileManager();
}catch (ExceptionFileNotReadable $e){
     $userInterface->openFileAccessManager();
}catch (ExceptionFileNotWriteable $e){
     $userInterface->openFileAccessManager();
}catch (ExceptionIsNotAString $e){
     $userInterface->showError($e->getMessage());
}catch (ExceptionIsNotXMLConform $e){
     $userInterface->openXMLEditor();
}catch (ExceptionDBException $e){
     $db->rollbackTransaction();
     $userInterface->showError($e->getMessage());
}catch (ExceptionEmailException $e){
     $db->rollbackTransaction();
     $userInterface->showError($e->getMessage());
}
?>
Semoga tulisan gue bisa memberi sedikit pencerahan.

7 comments:

necromancer said...

nice article bro, keep it up.

btw, itu kan nama exceptionnya custom. Berati kita perlu bikin exception sendiri yang extend Exception-nya PHP ato gimana ?

Arthur Purnama said...

Terima kasih bro.

Betul sekali bahwa Exception Class yang gue pakai dalam contoh-contoh diatas itu semuanya gue anggap sebagai custom Exception yang sudah dibuat atau didefinisikan terlebih dahulu.

Exception Class Standard yang sudah disediakan oleh PHP bisa lo lihat di Dokumentasi Standard PHP Library (SPL).

Selebihnya lo bisa mendefinisikan Exception lo sendiri yang inherit Exception Class dari SPL tersebut.

Bagaimana cara membuat Custom Exception bisa di lihat di contoh nomer 4 di PHP Manual-nya

Kalau lo mau PHP Error juga melempar Exception, loe bisa convert errornya menjadi ErrorException. Caranya juga lo bisa lihat di PHP Manual.

iTreumann said...

bos, artikelnya bagus, bikin gua ngerti.

tapi pengen nanya nih, kalo make class exception sebanyak itu, trus naro class-classnya yang enak gimana? satu file satu class exception, atau satu file ditaro semua class exception?

Arthur Purnama said...

gue sih biasanya ngikutin best practice ajah. satu file satu class / satu file satu exception class.
Exception classnya biasanya gue taro di satu directory yang isinya exception class saja.

Manda said...

Nice article bro. And nice coding style.

Arthur Purnama said...

makasih ^^

pqcms said...

nice artikle bro, gw book blog lo.. thanks bro.. walaupun ngerti cuma dikit..