24 September 2007

Adios, Jose!


Rasanya bagai disambar petir di siang bolong, ketika Jumat (21/9) yang lalu saya dikabari teman bahwa pelatih eksentik berkebangsaan Portugal yang menjuluki dirinya sendiri ‘The Special One’, Jose Mourinho, mengundurkan diri dari Chelsea FC. Awal mulanya saya cuma menganggap kabar tersebut sebagai gurauan saja. Saya sendiri baru benar-benar percaya setelah pada hari Minggu (23/9) menyaksikan siaran One Stop Football on Sunday di Trans7.
Kepergian pelatih ini juga mungkin akibat hasil tidak maksimal yang diperoleh dari pertandingannya yang terakhir, ditahan imbang 1-1 melawan Rosenborg FC (Champions League), dan sebelumnya 0-0 melawan Blackburn Rovers serta kalah dari tim tuan rumah Aston Villa 2-0 (EPL). Prestasi yang cenderung menurun ini, meski masih menempatkan Chelsea di papan atas persaingan EPL, namun tidak sesuai dengan ekspektasi sang pemilik Chelsea, Roman Abramovich.

Roman sebagai seorang biliuner Rusia yang selalu menginginkan hasil lebih tentu mempunyai ‘standar kemlaratan’ yang berbeda. Setelah sukses membawa FC Porto menjuarai liga Champion, Jose ditransfer ke Chelsea pada musim 2004-05. Kontan prestasi yang dihasilkannya luar biasa gemilang. Selama hamper setengah abad Chelsea belum mendapatkan gelar di Liga Premiere, langsung diberikannya pada musim itu. Dan langsung dua musim berturutan. Sayang kesempatan untuk mempertahankan dominasi tiga tahun berturutan dipatahkan Manchester United karena krisis lini belakang di tubuh Chelsea.
Enam tropi yang diberikannya selama tiga tahun membesut Chelsea rupanya belum cukup menghapus dahaga sang pemilik akan trofi Liga Champion. Selain dandanannya yang ‘dandy’, mulut pedas dan tingkah laku kontroversialnya membuat dirinya menjadi sosok yang paling menarik perhatian sekaligus menjadikan dirinya sebagai pribadi yang mudah mempunyai masalah. Pria yang pernah dinobatkan sebagai pemilik gaya berbusana terbaik di Britania Raya bersanding dengan Gwen Stefani di dandanan wanitanya ini, selain sering melakukan perang kata-kata dengan para rivalnya, juga acap kali melontarkan pernyataan pedas terhadap pemain dan petinggi klubnya sendiri.
Keputusannya untuk membangku cadangkan pemain kesayangan Roman, Shevchenko dan Ballack, bahkan tidak mencantumkan Ballack dalam daftar pemain Chelsea untuk babak kualifikasi grup liga Champion membuat posisinya seperti telur di ujung tanduk. Dan konfliknya dengan pemain Chelsea pun semakin membuat keputusannya untuk mundur menjadi tak terelakkan.
Dan yang saya sangat sesalkan adalah kenapa tidak ada pembelaan dari pihak Chelsea, mengingat prestasinya yang gemilang selama ini. Termasuk rekor kandang tak pernah terkalahkan terbanyak di EPL (64 pertandingan) yang mampu mematahkan rekor 63 kali milik Liverpool pada saat ditangani Bob Paisley (1978-80).
Sosok yang mampu memberi motivasi dan mendoktrin para pemain untuk menjadi juara benar-benar menjadi inspirasi bagi saya. Buat saya Jose ibarat Hitler untuk Nazi. Kepemimpinannya yang kuat dan eksentrik ini juga menjadi komoditas tersendiri bagi industri persepakbolaan Inggris. Saya yakin, lepasnya Mourinho akan mengurangi ‘nilai jual’ EPL. Bahkan seterunya di lapangan, Sir Alex Ferguson pun sangat menyayangkan mundurnya Mourinho. Mungkin tidak akan ada lagi sosok yang bisa diajak berbagi wine dan beradu komentar di luar lapangan. Dari semua pembeberan tadi, bagi diri saya sendiri, untuk saat ini saya tidak punya alasan untuk mencintai Chelsea lagi. Saya cuma berharap saya bisa melihat aksi-aksi Mourinho lagi di dalam dan luar lapangan. Dan saya pun berharap seandainya tulisan ini bisa menggugah para blogger lain yang memiliki persamaan dengan apa yang saya rasakan, untuk sama-sama menuliskan komentarnya. Semoga saja tulisan ini bisa ada artinya.


28 July 2007

CAKEPHP Chapter5: MODELS (Part1)

Mulai bagian ini anda harus pasang perhatian baik-baik. Pada manual resmi dari situs CakePHP.org sebelum Chapter Models ini ada satu chapter bernama Scaffold yang merupakan salah satu ‘hot feature’ dari Cake sendiri, dimana anda bisa membuat satu aplikasi lengkap cukup dengan menuliskan var $scaffold;, dan simsalabim!!! Akan tercipta aplikasi dengan action: index, add, edit, view, dan delete (sesuai dengan standar Cake, lengkap dari model hingga view.

Namun dalam membangun aplikasi sering kita melakukan kustomisasi, misal dalam data validation ataupun penambahan logic atau action tertentu. Jadi pembahasan pembuatan aplikasi dengan feature scaffolding dan Bake akan saya simpan dulu. Menurut hemat saya, jika kita memulai latihan dari yang berat, maka ketika kita diminta untuk ‘berlomba’ di level yang lebih ringan, semuanya akan terasa sangat mudah.

Section 1

Apakah Model Itu?

Dalam Chapter 2: Konsep Dasar, kita sudah menyinggung sedikit tentang konsep MVC, dimana Model menjadi bagian awalnya. Jika database ada di level presentation, maka Model berada pada level application logic. Boleh dikata bahwa suatu Model merupakan titik akses ke database, atau lebih tepatnya tabel di dalam database. Dalam konvensi Cake mengatur bahwa nama suatu tabel harus jamak, sedangkan nama Model merupakan bentuk tunggalnya (singular). Contoh: jika tabel bernama ‘users’ maka modelnya bernama ‘User’. Model juga dapat berisi validasi data, informasi asosiasi, dan metode lain yang berkaitan dengan tabel yang digunakan. Berikut contoh jika anda membuat Model User, yang kemudian disimpan di /app/model/user.php

//Untuk membuat model dalam Cake anda harus
menurunkannya dari AppModel
 
class User extends AppModel
{
    // Pastikan untuk memulai dengan mendifinasikan
variabel modelnya sendiri.
    var $name = 'User';
 
    // Kemudian diikuti validasi data.
    var $validate = array();
 
    // Dan sertakan asosiasi jika ada.
 
    var $hasMany = array('Image' =>
                   array('className' => 'Image')
                   );
 
    // Anda juga dapat menyertakan function buatan anda sendiri:
    function makeInactive($uid)
    {
        //Silahkan tulis logic-nya disini...
    }
}
 
?>


Section 2

Function dalam Model

Jika kita lihat contoh kode di atas dari sisi OOP/PHP, suatu model adalah suatu class yang merupakan turunan dari AppModel. Class AppModel sendiri aslinya terletak dalam direktori /cake, tapi jika anda ingin merubahnya sesuai kebutuhan aplikasi anda, salinlah ke app/app_model.php. Jika anda cermati isi filenya, AppModel ini sendiri juga merupakan turunan dari class Model yang merupakan library Cake standar yang ada di cake/libs/model.php. Jika anda ingin mengetahui lebih banyak tentang function dalam Model, silahkan kunjungi http://api.cakephp.org untuk info lebih lengkap. Yang akan dibahas disini adalah function yang paling sering digunakan.

Pengambilan Data

Berikut adalah beberapa cara mendapatkan data menggunakan model:

  • findAll
  • string $conditions
  • array $fields
  • string $order
  • int $limit
  • int $page
  • int $recursive

Mengembalikan field tertentu sampai dengan batasa $limut sesuai dengan $conditions (jika ada syarat/kondisi tertentu), dimulai dari halaman $page (defaultnya 1). $conditions berbentuk seperti statement SQL, semisal: $conditions=”description=’tutorial’ AND life_cycle>4”.

Ketika opsi $recursive diset lebih besar dari 1, operasi findAll() akan mengembalikan model yang diasosiasikan dengan model yang ditemukan oleh findAll().

  • find
  • string $conditions
  • array $fields
  • string $order
  • int $recursive

Mengembalikan field tertentu (atau seluruhnya jika tidak ditentukan) dari record pertama yang sesuai dengan $conditions.

Ketika opsi $recursive diset ke suatu nilai integer antara 1 dan 3, find() akan mengembalikan model yang diasosiasikan dengan model yang ditemukan oleh find().

  • findAllBy
  • string $value

Method ini bisa dipakai sebagai jalan pintas untuk mencari suatu nilai tertentu dari suatu field dalam tabel. Tinggal lekatkan field yang ingin anda cari, kemudian buatlah menjadi CamelCase (CamelCase adalah Case yang menjadikan setiap huruf awal dari setiap kata dalam suatu frase menjadi huruf capital, contoh: LastName, JobPosition, ProductOwner). Contoh (ketika digunakan dalam suatu Controller) seperti:

$this->Post->findByTitle('My First Blog Post');
$this->Author->findByLastName('Rogers');
$this->Property->findAllByState('AZ');
$this->Specimen->findAllByKingdom('Animalia');

Hasil yang didapatkan dalam bentuk Array seperti find() atau findAll().

  • findNeighbours
  • string $conditions
  • array $field
  • string $value

Method seperti ini mirip seperti jika kita menggunakan aplikasi kamus/dictionary. Biasanya jika kita mencari kata tertentu, maka akan diberikan pula kata yang mendekati bentuk kata tersebut. Hasil yang didapatkan berupa array, yang ditentukan oleh $field dan $value, dan dibatasi oleh $conditions. Namun hanya dapat digunakan pada tipe data ‘numeric’ dan ‘date’. Contoh:

class ImagesController extends AppController
{
function view($id)
{
// Ini cara untuk mengambil data sebuah Image

$this->set('image', $this->Image->find("id = $id");

// Tapi kita juga ingin melihat yang sebelum dan sesudahnya...

$this->set('neighbours', $this->Image->findNeighbours(null, 'id', $id);

}
}

Kode di atas memberi kita suatu array $image[‘Image’], sekaligus dengan $ neighbours['prev']['Image']['id'] dan $neighbours['next']['Image']['id'] pada sisi view.

  • field
  • string $name
  • string $conditions
  • string $order

Mengembalikan sebuah string dari field tunggal dari record pertama sesuai $conditions dan urut berdasar $order.

  • findCount
  • string $conditions

Mengembalikan jumlah record sesuai $conditions.

  • generateList
  • string $conditions
  • string $order
  • int $limit
  • string $keyPath
  • string $valuePath

Method ini merupakan cara cepat untuk mendapatkan sederet daftar pasangan nilai kunci –sangat cocok dipakai untuk membuat tag select HTML dari daftar Model aplikasi anda. Gunakan $conditions, $order, dan $limit sama seperti pada findAll(). $keyPath dan $valuePath merupakan tempat dimana Model dapat menemukan letak key dan value untuk daftar tadi.. Sebagai contoh, jika anda ingin meng-generate suatu daftar/list berdasar aturan pada model Role, dengan key berupa ids integer, maka bisa berbentuk seperti ini:

$this->set(
'Roles',
$this->Role->generateList(null, 'role_name ASC', null, '{n}.Role.id', '{n}.Role.role_name')
);

//Kode di atas akan menghasilkan:
array(
'1' => 'Account Manager',
'2' => 'Account Viewer',
'3' => 'System Manager',
'4' => 'Site Visitor'
);
  • read
  • string $fields
  • string $id

Gunakan read() ini untuk memperoleh field dan nilainya dari record yang telah diload atau record yang ditentukan oleh $id.

Sebagai catatan, read() hanya akan mengambil data dari model asosiasi level pertama tanpa mempedulikan hasil $recursive dalam model. Untuk memperoleh level tambahan, gunakan find() atau findAll().

  • query
  • string $query

  • execute
  • string $query

Perintah SQL biasa dapat dipanggil dengan method query dan execute. Perbedaan antara keduanya adalah query() digunakan untuk membuat custom SQL query (hasilnya dikembalikan). Sedangkan execute() digunakan untuk membuat custom SQL command (tidak membutuhkan nilai dikembalikan). Berikut contoh perintah SQL dengan query():

query("SELECT first_name FROM posters_table
WHERE poster_id = 1");
$firstName = $ret[0]['first_name'];
return $firstName;
}
}
?>

Kondisi Pencarian Kompleks (menggunakan array)

Kebanyakan pemanggilan pencarian dalam model dilakukan dengan melibatkan kondisi tertentu. Pendekatan yang paling sederhana adalah dengan menggunakan klausa WHERE dalam potongan kode SQL. Tetapi jika anda butuh sesuatu yang lebih, anda dapat menggunakan array yang membuat query menjadi lebih mudah untuk dibuat dan dibaca. Syntax ini dapat memisahkan setiap elemen dalam query (field, value, operator, dll) ke bagian yang bisa dimanipulasi. Salah satu contoh sederhana query berbasis array:

$conditions = array("Post.title" => "This is a post");

//Contoh penggunaan dalam suatu model:
$this->Post->find($conditions);

Kode di atas menjelaskan bahwa query akan mencari dalam Model Post yang mempunyai Title=”This is a post”. Untuk diperhatikan, bahwa lebih baik jika anda melakukan query dalam Cake selalu merujuk kepada Model, bukan tabel. Ini untuk menghindari terjadinya collision dalam aplikasi anda. Ok, lalu bagaimana jika kita ingin menggunakan operator? Hal tersebut sama mudahnya. Katakan jika kita ingin menemukan seluruh Post dimana title nya bukan “This is a post”:

array("Post.title" => "<> This is a post")

Cake dapat menangani semua operator pembanding SQL, termasuk ekspresi seperti LIKE, BETWEEN, atau REGEX. Yang jadi catatan adalah jangan lupa memberi spasi antara operator dan ekspresi atau value. Satu-satunya pengualian disini adalah ekspresi IN (…). Baik, sekarang kita ingin mencari Post dengan beberapa value:

array("Post.title" => array("First post", "Second post", "Third post"))

Jika kita ingin membatasi lagi pencarian lagi caranya hanya dengan menambahkan pasangan key/value ke array:

array( "Post.title" => array("First post", "Second post", "Third post"), "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")))

Secara default, Cake menggunakan operator Boolean AND untuk operasi join seperti di atas. Jika kita ingin memakai operator Boolean lain, maka bisa dengan cara seperti ini:

array("or" => array ( "Post.title" => array("First post", "Second post", "Third post"), "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")) ))

Cake menerima semua operand Boolean, seperti AND, OR, NOT, XOR, dll., dan bisa ditulis huruf kapital maupun tidak.Kondisi ini juga dapat dibuat bersarang. Berikut adalah contoh untuk query dengan tabel Posts dan Authors punya hubungan hasMany/belongTo, yang akan menghasilkan LEFT JOIN pada sisi Post. Kondisinya adalah anda ingin mencari kata ‘magic’ atau yang dibuat dua minggu yang lalu, tapi dibatasi pada Post yang ditulis oleh ‘Bob’:

array ("Author.name" => "Bob", "or" => array ( "Post.title" => "LIKE %magic%", "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks") ))

Menyimpan Data

Untuk menyimpan data ke dalam model, tentu anda harus mengisinya dengan data yang ingin anda simpan. Data yang disimpan dengan method save() menghasilkan bentuk seperti berikut:

Array( [NamaModel] => Array ( [namafield1] => 'value' [namafield2] => 'value' ))

Cara paling mudah untuk mendapatkan data seperti ini adalah dengan menggunakan helper HTML (akan dibahas setelah pembahasan MVC), karena akan membuat elemen-elemen form yang namanya sesuai dengan aturan di Cake. Anda tidak harus menggunakannya: pada pokoknya hanya pastikan nama elemen formnya berbentuk seperti data[NamaModel][namafield]. Namun bagaimanapun juga $html->input('Model/fieldname') adalah cara termudah.

Data yang dikirim dari form secara otomatis akan terformat seperti di atas dan diletakkan dalam $this->data didalam Controller. Berikut contoh fungsi edit pada Controller Property:

function edit($id)
{

//Catatan: Model Property secara otomatis diletakkan oleh Cake ke $this->Property.

// Mengecek apakah form diisi data...
if (empty($this->data))
{
$this->Property->id = $id;
$this->data = $this->Property->read();//membaca field pada form
}
else
{
// Perhatikan cara menyimpan data berikut. Cake juga secara otomatis dapat melakukan validasi checking
if ($this->Property->save($this->data['Property']))
{
//Pesan Flash yang ditampilkan dan redirect.
$this->flash('Your information has been saved.',
'/properties/view/'.$this->data['Property']['id'], 2);
}
//jika ada field yang invalid atau gagal menyimpan, Cake juga akan merender halaman error.
}
}

Perhatikan bagaimana operasi menyimpan ini terletak pada suatu kondisional validasi sesuai aturan yang telah dibuat. Lebih lanjut tentang Validasi Data akan dibahas nanti. Sekarang jika anda tidak ingin save() memvalidasi data anda gunakan save($data, false).

Beberapa fungsi lain yang berguna:

  • del
    • string $id
    • boolean $cascade

Menghapus model sesuai $id.

Jika Model mempunyai ke Model-Model lain, dan ‘dependent key’ telah terdeklarasikan dalam array asosiasi, maka method del() ini akan menghapus Model-Model lain tersebut jika $cascade diset ‘true’.

del() akan mengembalikan nilai true jika sukses.

· saveField

o string $name

o string $value

Digunakan untuk menyimpan nilai field tunggal.

· getLastInsertId

Mengembalikan nilai ID dari record yang terakhir dibuat.

Callback Model

Dalam Model Cake, dikenal juga Callback yang memperbolehkan anda untuk melakukan sesuatu sebelum atau setelah suatu operasi. Berikut method Callback dalam Cake:.

· beforeFind

o string $conditions

Set ke ‘return true’ ketika anda ingin method find dieksekusi, dan ‘false’ jika ingin menghentikan perintah find.

· afterFind

o array $results

Gunakan method callback yang satu ini jika ingin memodifikasi hasil operasi find() atau jika ingin melakukan operasi lain terhadap hasil find(). Parameter untuk method ini tentu saja hasil operasi find, dan keluarannya berupa hasil yang sudah diubah.

  • beforeValidate

Gunakan callback ini untuk memodifikasi data Model sebelum divalidasi. Bisa juga digunakan untuk aturan validasi yang lebih kompleks, menggunakan Model::invalidate().Dalam konteks ini, data Model dapat diakses melalui $this->data. Method ini juga harus diset ke true, dan sebaliknya false jika ingin menghentikan save()..

  • beforeSave

Callback ini juga diset ke true jika operasi save() ingin berlanjut, dan false jika ingin digagalkan. Contoh penggunaan beforeSave dalam penanganan format waktu di suatu database:

// Berikut adalah field Date/time yang dibuat helper HTML:

// Kode ini akan dilihat di View



$html->dayOptionTag('Event/start');

$html->monthOptionTag('Event/start');

$html->yearOptionTag('Event/start');

$html->hourOptionTag('Event/start');

$html->minuteOptionTag('Event/start');



/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/



// Kode berikut akan ada di Model Event, callback beforeSave digunakan untuk merubah format waktu sebelum disimpan ke database:



function beforeSave()

{

$this->data['Event']['start'] = $this->_getDate('Event', 'start');



return true;

}



function _getDate($model, $field)

{

return date('Y-m-d H:i:s', mktime(

intval($this->data[$model][$field . '_hour']),

intval($this->data[$model][$field . '_min']),

null,

intval($this->data[$model][$field . '_month']),

intval($this->data[$model][$field . '_day']),

intval($this->data[$model][$field . '_year'])));

}
  • afterSave
  • beforeDelete

Set ke ‘return true’ ketika anda ingin penghapusan dieksekusi, dan ‘false’ jika ingin menghentikan perintah penghapusan.

  • afterDelete

Section 3

Variabel Model

Ketika anda bekerja dengan Model, ada sejumlah variabel yang bisa anda manfaatkan untuk mendapat fungsi khusus dari Cake.

$primaryKey

Jika suatu Model merupakan suatu tabel dalam database, dan primary key tabel tersebut tidak bernama ‘id’, anda bisa guakan variabel ini untuk memberitahukan Cake nama primary key-nya.

$recursive

Variabel ini mengatur kedalaman tingkat pengambilan Model yang terasosiasi ketika menggunakan operasi find() dan findAll().

Contoh : seandainya anda mempunyai Groups yang mempunyai banyak Users yang masing-masing mempunyai Articles.

Opsi dalam Model::recursive

$recursive = 0

Cake mengambil data Group

$recursive = 1

Cake mengambil sebuah Group dan User yang terasosiasi

$recursive = 2

Cake mengambil sebuah Group, User yang terasosiasi, dan Articles yang dimiliki User tersebut

$transactional

Memberitahukan Cake apakah Model dapat melakukan transaksi atau tidak (seperti begin/commit/rollback). Menggunakan nilai Boolean. Hanya dapat untuk database tertentu.

$useTable

Jika tabel dalam database anda tidak berbentuk plural/mendapat akhiran ‘s’, dan anda tidak ingin menggantinya, set lah variabel ini ke nama tabel yang ingin anda gunakan.

$validate

Merupakan array yang digunakan untuk memvalidasi data ke model (akan ada pembahasan lebih lanjut di Chapter lain).

$useDbConfig

Masih ingat setting database pada Chapter sebelumnya di /app/config/database.php? Gunakan variabel ini untuk berpindah antara nama koneksi database yang ada di file tersebut. Nilai defaultnya adalah ‘default’.


22 July 2007

CAKEPHP Chapte4: Konfigurasi

Sebelum memulai konfigurasi di Cake, saya minta anda untuk membuat suatu database bernama ‘blogcake’ lebih dulu. Silahkan buka phpMyAdmin dari web browser anda, cari kolom Create new database, ketik blogcake, kemudian klik tombol create. Jika benar, anda akan lanjut ke halaman baru yang menyatakan anda telah sukses membuat database baru dan anda sudah langsung memakai database tersebut. Sekarang klik tab SQL yang ada di atas frame sebelah kanan. Copy query berikut dan paste ke text area di halaman tersebut.

CREATE TABLE posts (

id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,

title VARCHAR(50),

body TEXT,

created DATETIME DEFAULT NULL,

modified DATETIME DEFAULT NULL

);

/* Kemudian masukkan beberapa Post untuk testing*/

INSERT INTO posts (title,body,created)

VALUES ('The title', 'This is the post body.', NOW());

INSERT INTO posts (title,body,created)

VALUES ('A title once again', 'And the post body follows.', NOW());

INSERT INTO posts (title,body,created)

VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());


Klik go. Selanjutnya baru kita memulai tahap konfigurasinya.



Section 1

Konfigurasi Database

Konfigurasi database pada Cake terdapat pada file app/config/database.php. Namun pada instalasi awal Cake tidak terdapat file tersebut, jadi anda harus mengcopy dari file database.php.default. Ubah namanya menjadi database.php saja.Buka file tersebut dengan web editor anda (Dreamweaver, Notepad++, EditPlus, atau yang lain) lihat pada bagian:

var $default = array('driver' => 'mysql',

'connect' => 'mysql_connect',

'host' => 'localhost',

'login' => 'user',

'password' => 'password',

'database' => 'project_name',

'prefix' => '');

Ubah bagian login dan password sesuai setting MySQL anda. Kemudian ‘project_name’ pada database menjadi blogcake seperti yang sudah kita buat tadi.

Catatan untuk variabel ’prefix’ : jika anda memasukkan string ke dalamnya, maka jika anda melakukan query SQL untuk tabel akan mengarah ke prefix_namatabel. Contoh jika anda punya tabel posts seperti di atas, dan ’prefix’=>’blog_’, maka query akan mengarah ke ‘blog_posts’. Sekali anda mendefinisikan prefix, keseluruhan tabel dalam database harus mendapat imbuhan prefix tersebut. Dan untuk tabel HABTM join, anda cukup menambah prefix sekali: blog_categories_posts, bukan blog_categories_blog_posts.

CakePHP mendukung beberapa driver dabatabase berikut:

1. mysql

2. postgres

3. sqlite

4. pear-drivername (contoh pear-mysql)

5. adodb-drivername

Kata kunci 'connect' pada koneksi $default mempersilahkan anda untuk menentukan apakah koneksi akan persistent atau tidak. (Baca komentar pada file database.php untuk menentukan tipe koneksi lebih lanjut). Sementara pada tutorial ini, kita isi dengan ‘mysql_connect’ saja.

Selain itu, tabel dalam database anda juga harus mengikuti konvensi yang digunakan Cake. Memang kelihatannya cukup merepotkan pada mulanya, namun anda cukup percaya saja, kelak anda akan merasakan manfaatnya ketika memulai memaintenance aplikasi web anda, dan anda akan ‘tersihir’ bagaimana Cake dapat menghasilkan aplikasi berskala besar dengan cepatnya jika anda benar-benar mengikuti aturan Cake.Selain itu, anda bisa mendaftarkan aplikasi anda ke komunitas open source Cake. Ok, inilah aturan untuk tabel:

1. Nama tabel biasanya berupa kata jamak/plural dalam bahasa Inggris, seperti “users, posts, polls”. Sebenarnya dalam bahasa Indonesia pun tidak masalah, cukup dengan menambahkan akhiran –s dibelakang nama tabel, contoh: “artikels, divisis, kategories”. Namun untuk Model (ingat konsep MVC-nya) untuk tabel yang bersangkutan nama modelnya berupa kata tunggal.

2. Dalam tabel harus ada primary key bernama ‘id’.

3. Jika ada relasi, gunakan foreign key seperti ‘article_id’. Nama tabel berupa kata tunggal/singular, diikuti underscore, kemudian diakhiri ‘id’.

4. Jika dalam tabel terdapat kolom ‘created’ dan/atau ‘modified’, Cake secara otomatis akan mengisinya sesuai dengan keadaan.

Selain $default dalam database.php, anda juga akan melihat seting $test connection di bawahnya. Silahkan isi sesuka anda dengan aturan sama seperti di atas, kemudian anda bisa menggunakannya dengan cara seperti:

Sampai disini, kita akan kembali mengetes instalasi Cake kita. Jika benar, anda akan mendapatkan hasil seperti ini:

Section 2

Konfigurasi Umum

Konfigurasi umum/global Cake dapat ditemukan pada file app/config/core.php. Sebenarnya tidak ada yang anda perlu ubah untuk tutorial ini, namun saya akan tetap memberitahu anda beberapa point penting di file ini.

DEBUG: defaultnya bernilai ‘1’, akan menampilkan pesan kesalahan pada kode yang anda buat pada aplikasi anda. Jika anda mengeset ke ‘2’, maka hasil query SQL akan ditampilkan di sisi bawah layar halaman. Selain 0, Cake akan merender error page sesuai kesalahan code pada aplikasi anda, seperti “Missing Controller”, “Missing Action”, dll.

CAKE_SESSION_COOKIE: ubah nilainya ke nama cookie yang anda gunakan untuk user session di aplikasi anda.

CAKE_SECURITY: ubah nilai ini untuk menentukan pengecekan level session. Cake akan menentukan akhir session, menggenerate session ids baru, dan menghapus session lama berdasar nilai yang anda masukkan. Nilai yang bisa anda tulis adalah:

1. high: session akan berakhir setelah 10 menit dari tidak adanya aktifitas apapun, session ids diregenerasi pada setiap request.

2. medium: session akan berakhir setelah 20 menit dari tidak adanya aktifitas apapun.

3. low: session akan berakhir setelah 30 menit dari tidak adanya aktifitas apapun.

CAKE_SESSION_SAVE: menentukan bagaimana data session akan disimpan. Silahkan memasukkan salah satu nilai berikut (urut dari yang paling low-security sampai high-security):

1. cake: data session akan disimpan dalam tmp/ di instalasi Cake anda.

2. php: data session akan disimpan sesuai definisi php.ini.

3. database: data session akan disimpan ke suatu tabel sesuai di variabel $default, biasanya bernama cake_sessions. Di artikel lain saya akan mencontohkan penggunaan database untuk penanganan sessions. Namun sementara ini kita setting ke ‘php’ dulu.

Section 3

Konfigurasi Routing

Routing merupakan bagian dari mod_rewrite PHP yang dapat ‘memetakan’ URL ke controller/action/params. Dengan routing URL bisa lebih cantik dan lebih dapat dikonfigurasi. Routing dapat ditentukan lewat file app/config/routes.php. Pattern/pola yang digunakan untuk routing seperti berikut:

Dimana:

1. URL adalah regular expression (regex) dari URL Cake yang akan anda petakan,

2. controllername adalah nama controller yang anda akan sertakan

3. actionname adalah nama action dari controller

4. firstparam adalah nilai parameter pertama dari action yang anda tentukan

Parameter lain yang menyertai firstparam akan dipassing sebagai parameter ke action controller.

Dalam tutorial ini tidak ada yang perlu diubah dari file konfigurasi routing tersebut.

Section 4

Konfigurasi Routing Lanjut: Admin dan Webservices

Masih dalam file yang sama (/app/config.core.php) anda bisa mengatur penanganan URL untuk admin dan webservices. Hal pertama yang kita bahas adalah routing URL admin. Tentu dalam aplikasi yang kita buat, ada hak istimewa sebagai admin yang kita berikan kepada user tertentu (Lebih lanjut tentang pemberian hak akses akan kita pelajari di fitur ACL=Access Control List). Biasanya saya lebih menyukai URL berbentuk /admin/posts/add atau /admin/posts/edit daripada /posts/adminAdd atau /posts/adminEdit.

Untuk mengaktifkan fungsi ini di Cake, yang pertama kali dilakukan adalah menghilangkan komentar berupa tanda double slash (//) dari CAKE_ADMIN pada file /app/config/core.php. Nilai default dari CAKE_ADMIN ini adalah ‘admin’, tapi anda juga bisa mengubahnya ke nilai lain yang anda suka, seperti ‘superuser’, ‘su’, ‘atur’, dll. Ingatlah nilai yang anda masukkan ini, karena akan digunakan untuk controller (akan dibahas nanti). Nantinya, action dari admin ini akan bernama namaadmin_namaaction(). Berikut beberapa contoh URL, CAKE_ADMIN, dan action di controller:


/admin/products/add CAKE_ADMIN = 'admin'

Nama action di ProductsController = 'admin_add()'


/superuser/news/post CAKE_ADMIN = 'superuser'

Nama action di NewsController = 'superuser_post()'


/su/posts/delete CAKE_ADMIN = 'su'

Nama action di PostsController = 'su_delete()'


Setelah diset variabel CAKE_ADMIN, maka anda dapat dengan mudah menggunakan routing admin ini dengan menggunakan:

$this->params[CAKE_ADMIN];

atau

$this->params['admin'];

(dengan anggapan bahwa ‘admin adalah variabel dari CAKE_ADMIN).

Sesuai dengan catatan dari manual yang ada pada situs CakePHP.org bahwa dengan mengaktifkan routing admin ini tidak berarti anda menggunakan metode otentifikasi ataupun security tertentu. Anda harus mengesetnya sendiri, yang akan dijelaskan di chapter lain. (Sekali lagi) Sabar…

Dengan cara yang sama, anda dapat mengaktifkan routing untuk fitur webservices sama mudahnya. Pertama, set WEBSERVICES di file yang sama ke ‘on’, kemudian anda tinggal menambahkan beberapa logic di Controller anda. Jadi, dengan mengaktifkan WEBSERVICES ini anda mengaktifkan suatu hal yang hampir sama dengan routing admin, kecuali beberapa prefix untuk routing ini sudah tersedia, seperti:

1. rss

2. xml

3. rest

4. soap

5. xmlrpc

Nantinya anda akan punya alternative View yang bisa diakses pada /rss/namaController/namaAction atau /soap/namaController/namaAction. Anda cukup membuat satu action untuk dua view: satu untuk halaman HTML biasa, dan yang lain untuk pemakai webservice.


18 July 2007

CAKEPHP Chapter3: Praktek Instalasi

Untuk melakukan instalasi CakePHP, dibutuhkan sebuah server yang memuat seluruh library dan program yang dibutuhkan untuk menjalankan CakePHP. Syarat yang harus dipenuhi dalam server itu adalah:

  1. Sebuah server HTTP (seperti Apache) dengan session enabled dan mod_rewrite(mod_rewrite ini lebih disukai dalam keadaan enabled)
  2. PHP 4.3.2 atau di atasnya (5.x)
  3. Database engine(MySQL, PostgreSQL, dan yang mendukung ADODB)

Ketiga syarat tersebut biasa menjadi satu paket yang dikenal dengan AMP (Apache, MySQL, PHP). Ada beberapa pilihan paket instalasi yang mudah digunakan, seperti PHPTriad, Apache2triad, XAMPP, atau AppServ. Penulis menggunakan yang paling terakhir. Yakni AppServ 2.5.4a (Apache 2.0.54, PHP 5.0.4, MySQL 4.1.12a, dan dilengkapi phpMyAdmin 2.6.2-pl1). Silahkan anda download dari sini. Jika sukses menginstal AppServ akan didapat tampilan berikut dengan mengetikkan localhost di browser anda.


Setelah anda mendapatkan CakePHP dari chapter1 sebelumnya, sekarang letakkan file .ZIP atau bentuk file yang terkompres tersebut ke DocumentRoot/webroot anda. Kalau anda mengikuti memakai AppServ yang terinstal di C:\, maka dalam file httpd.conf apache biasanya sudah tersetting ke C:/appserv/www. Selanjutnya ada dua cara instalasi CakePHP: menggunakan development setup, yang mempersilahkan untuk melihat sekaligus beberapa aplikasi CakePHP dalam satu domain, atau dengan production setup, yang memperbolehkan satu aplikasi CakePHP dalam satu domain.

Sebelum mensetup Cake, pastikan mod_rewrite dalam httpd.conf Apache diperbolehkan. Caranya cari dalam folder instalasi Apache file conf/httpd.conf. Edit dengan notepad, hilangkan tanda pagar (#) di awal baris berikut:

 LoadModule rewrite_module modules/mod_rewrite.so

Pastikan juga agar Apache mengijinkan akses .htaccess override. Di file yang sama, cari kata-kata AllowOverride pada atau , set ke All, sehingga menjadi AllowOverride All.


Jika anda mengikuti langkah sebelumnya, untuk menginstal development setup anda tinggal mengekstrak ke folder /appserv/www. Sehingga nampak seperti berikut:

/appserv

/www

/cake

/app

/cake

/vendors

.htaccess

index.php

Ketikkan localhost/cake pada browser anda, maka anda akan mendapatkan tampilan seperti berikut:

(Perhatikan Your database configuration file is not present ! Pesan tersebut muncul karena memang sampai sejauh ini kita belum mengonfigurasi database apa yang aka digunakan. Harap sabar…)

Nantinya, jika mod_rewrite dalam keadaan enabled, maka URL anda akan berbentuk seperti ini:

www.example.com/cake/controllerName/actionName
/param1/param2
Contoh jika kita membuat Controller bernama ‘posts’, action-nya ‘edit’, dan parameter-nya adalah ‘1’ di localhost/cake, maka bentuk URL-nya: localhost/cake/posts/edit/1
(Sebenarnya ada beberapa cara lain untuk men-setup Cake ke dalam Web Server. Tapi untuk sementara kita pakai cara yang paling sering dan paling mudah digunakan dulu)

31 May 2007

Retouch Photo Rusak


Ini karya saya pake Photoshop. Gak susah, cuma butuh waktu 1 1/2 jam buat benerin foto ini. Pertama Edit Curves, terus pake Clone Stamp dan Patch Tool. Thanks buat Nisa atas contoh foto yang sempurna.


Sebelum:



Sesudah:


Ada yang mau tutorialnya? Kasih comment dulu dunk... :)


Bangsa Semut pake IKON Lucu

Awalnya saya ngrasa ada yang 'membosankan' lihat Bangsa Semut. Yah, banyakan tulisan gak ada gambarnya. Bukan apa-apa, tapi emang rada males ngerjain gambar-gambarnya. Kemarin kebetulan mood-nya lagi pengin utak-atik CorelDraw sama Photoshop. Sekalian degh, saya bikinin ikon yang -menurut saya- cukup lucu-lucu ini. Mudah-mudahan bisa mempermudah milih bacaan, n bikin ratingnya naik. (he... laris manis). Kalo artinya saya kira udah jelas khan?


27 May 2007

CakePHP Chapter2: Konsep Dasar

Sebelum memulai instalasi dan praktek lainnya, ada baiknya kita mengenal konsep yang diterapkan dalam CakePHP. CakePHP menggunakan apa yang disebut dengan pola Model-View-Controller (MVC). MVC adalah pola desain software yang membantu secara logis memisahkan kode program anda, membuatnya lebih reusable, maintainable, dan lebih baik secara keseluruhan.


Dalam istilah Cake, Model mewakili bagian table/record database, dan hubungannya dengan table/record yang lain. Model juga dapat berisi aturan validasi data, yang biasa diterapkan ketika data model di-insert atau update.

View mewakili file tampilan Cake, yang merupakan HTML biasa dengan tambahan kode PHP.

Sedangkan Controller dalam Cake menangani permintaan dari server. Controller menangani user input (URL dan data POST), menerapkan business ligic, memakai Model untuk membaca dan menulis data dari dan ke database dan sumber lainnya, serta mengirimkan data keluaran ke file View yang sesuai.

Untuk memudahkan pengorganisasian aplikasi, Cake menggunakan MVC tidak hanya untuk mengatur bagaimawa objek berinteraksi dalam aplikasi, tapi juga bagaimana file-file disimpan, yang akan dijelaskan nanti.

Ok, sekarang kita beralih melihat susunan file/folder dalam CakePHP. Jika anda meng-unpack file yang sudah didownload dari chapter 1 sebelumnya, anda akan melihat bahwa ada beberapa folder dalam Cake. Namun ada tiga folder utama: app, cake, dan vendors. Secara lengkap berikut susunan folder dalam CakePHP:


/app
    /config          - Berisi file-file konfigurasi database, ACL, dll 
 
    /controllers     - Controllers aplikasi anda 
        /components  - Components aplikasi anda
 
    /index.php       - mempersilahkan anda untuk mengembangkan cake dengan /app
sebagai DocumentRoot
 
    /models          - Models aplikasi
 
    /plugins         - Plugins aplikasi
 
    /tmp             - digunakan untuk caches dan logs
(set folder ini menjadi writable)
 
    /vendors         - Berisi third-party libaries untuk aplikasi
 
    /views           - Views aplikasi
        /elements    - Elements, bagian dari tampilan
        /errors      - Custom error pages
        /helpers     - Helpers
        /layouts     - Application layout files
        /pages       - Static views 
 
    /webroot         - DocumentRoot untuk aplikasi
        /css
        /files
        /img
        /js
 
/cake                - Library inti Cake. Jangan edit file apapun dalam folder ini.
 
index.php           
 
/vendors             - Untuk server-wide third-party libraries.
 
VERSION.txt          - Versi Cake yang anda gunakan


CAKEPHP Chapter1: Pindah Framework Yuk...


Dunia tehnologi informasi yang saya tekuni saat ini benar-benar sedang berevolusi. Banyak yang bisa dijabarkan dari kalimat tadi. Namun saya hanya akan bercerita mengenai bahasa pemrograman yang saya pernah praktekkan sendiri.

Sejak masih SMP saya sudah belajar komputer (sekitar tahun 1998). Waktu itu komputer yang saya punyai adalah Intel 80486 dengan HD cuma 250 MB. Saya sudah belajar DOS 6.0 dan Windows 3.11. Bahasa pemrograman yang saya pelajari adalah QBASIC. Sifatnya masih main-main, penasaran.

SLTA saya harus berpisah dengan komputer saya. Saya disekolahkan oleh orang tua ke luar kota. Kadang masih bisa ngutak-atik komputer di rental pengetikan. Karena komputer di tempat rental tidak terpasang developer tools, seperti aplikasi pemrograman, saya hanya bisa sedikit ‘iseng’ bikin-bikin file BATCH atau VBScript. Pernah juga bikin virus macro pakai editor internal yang ada di Word. Kadang masih sempat main-main VB di rumah pake komputer Via 1 GHz Pro.


Setelah tiga tahun tidak ada ‘pegangan’, akhirnya saya punya komputer lagi. Kali ini Pentium 4 1,8 Ghz dengan HD 120 GB. Cukup banyak yang saya pelajari, walau belum cukup untuk dibilang ‘lengkap’. He…

Saya sempat belajar C++, GCC, Gambas, Phyton, ASP, .NET, dan PHP. Di sisi DBMS saya juga pernah pakai Access, SQL Server, MySQL, PostgreSQL. Kesemuanya hanya pada samapai tingkatan ‘rata-rata’.

Selalu ada keraguan untuk memperdalam suatu bahasa pemrograman dalam diri saya. Karena sebagus apapun kita menguasai suatu bahasa pemrograman, biasanya ada saja bahasa pengganti yang lebih matang, yang seringnya berbeda sama sekali konsepnya dengan yang sudah kita pelajari. Sejauh pengamatan saya, sepertinya hanya Java yang relatif stabil dan bisa diandalkan untuk program berskala besar sampai beberapa tahun ke depan. Saya juga sudah belajar sedikit tentang Java. Namun saya tidak ingin mengulasnya, karena sudah banyak tulisan yang membahasnya.

Kali ini saya ingin ngomong masalah framework. Kita bikin tulisan ini ringan-ringan saja. Agar anda dapat mengikutinya dengan mudah. Definisi yang saya pakai pun seringkali tidak baku dan tidak mengarah ke suatu referensi. Siap?

Baik, pertanyaan yang pertama: apa sih framework itu? Gampang aja: framework kita artikan kerangka kerja. Terus kenapa kita butuh framework? Banyak alasan yang bisa dikemukakan. Tapi kalau saya pribadi cenderung menyukai kemudahan yang ditawarkan dan sudah bosan dengan metode pengembangan yang ngasal dan gitu-gitu melulu. Nanti akan lebih saya jelaskan.

Ok, sekarang saya persempit lagi bahasannya dengan menambah satu kata: ‘PHP’. Jadilah framework PHP. PHP untuk saat ini masih bisa diandalkan untuk pengembangan aplikasi berbasis web. Keistimewaan PHP yang paling saya sukai adalah cross-platform, open-source, dan mendukung konsep OOP. Sekarang contoh nyata framework PHP tuh seperti apa?

Ada banyak contoh. Yang berbasis CMS seperti PostNuke dan Mambo. Dan yang lebih keren seperti Mojavi, WACT, PHP.MVC. Atau yang menekankan reusable code, event driven programming, dan berbasis komponen seperti Prado. Lagi-lagi semuanya punya kelebihan dan kekurangan. Dan saya kira sudah banyak referensi yang bahas CMS ataupun Prado. Sedang seperti Mojavi cs. belum banyak. Tapi saya pilih yang lebih populer dan memiliki komunitas yang aktif, yaitu CakePHP. Kalau boleh jujur, sebetulnya konsep yang ditawarkan Prado juga menarik. Namun sayang, untuk kemudahan dalam menemukan aplikasi yang mendukung untuk menulis kode komponen Prado secara auto-complete belum ada. Sedangkan CakePHP masih mengandalkan kode-kode dari PHP dan HTML.

Keistimewaan CakePHP yang saya sukai diantaranya:

  1. Scaffolding: fitur yang memungkinkan menguji aplikasi tanpa menuliskan kode CRUD (Create, Read, Update, Delete).
  2. Kompatibel dengan PHP4 dan PHP5
  3. ACL (Access Control List)
  4. Request dispatcher, yang membuat URL menjadi ‘lebih indah’
  5. Berbasis MVC (Model, View, Controller)
  6. Built in validation, dan masih banyak lagi fitur menarik lainnya.

Saya ingin memandu anda secara perlahan, sekaligus kita belajar bersama. Namun jika anda membutuhkan referensi resminya bisa anda kunjungi di http://cakephp.org.

Tapi sebelum anda memulai, anda bisa mendapatkan CakePHP dengan:

1. Download versi stable-nya di http://cakeforge.org/projects/cakephp/.

2. Versi nigthly build (stable dan ditambahkan bug fixes) dari http://cakephp.org/downloads/index/nightly.

3. Menggunakan SVN client ke https://svn.cakephp.org/repo/trunk/cake/

Happy CakePHP! :p


22 May 2007

HOT SPOT: Kebutuhan, Peluang, dan Ancaman


Popularitas Tukul Arwana dan jargonnya “kembali ke laptop” benar-benar bisa membuat suatu hal yang signifikan, termasuk di sekitar Yogyakarta. Lihatlah di sekitar kota, khususnya di kampus-kampus, mall/pusat perbelanjaan, ataupun resto/café di bilangan utara Kota Yogyakarta. Banyak anak-anak muda, yang notabenenya mahasiswa, membawa gadget yang biasa digunakan Tukul untuk memandu acaranya itu. Umumnya mereka membawa laptop yang sudah dipersenjatai dengan WiFi (Wireless Fidelity) Card atau kadang disebut juga Wireless LAN Card atau Wireless Card saja. Sebuah piranti untuk laptop yang menghubungkan laptop dengan Access Point(AP) atau Router untuk mengakses internet. Bagi laptop baru, umumnya sudah ter-install WiFi card. Sedangkan laptop lama, cukup dengan mengeluarkan uang dua ratus ribuan, anda sudah dapat menikmati layanan internet gratis di berbagai tempat di Yogyakarta.
Layanan internet gratis di sekitar wilayah AP ini biasanya disebut hot spot. Hot spot yang daya jangkaunya hanya beberapa meter saja ini juga punya standarisasi sendiri. Namun yang paling banyak diterapkan di Yogyakarta, adalah 802.11 b dan 802.11 g yang masing-masing memiliki kecepatan 11 Mbps dan 54 Mbps atau 108 Mbps dengan tambahan Turbo G (saya belum menemukan yang 802.11 a). Kedua standarisasi ini bekerja pada frekuensi 2,4 GHz.
Untuk memanfaatkan Hot Spot ini, ada berbagai macam kebijakan yang diterapkan oleh provider-nya. Ada yang bisa langsung terhubung dengan AP (seperti di Ambarukmo Plaza/Citranet, Kedai Nusantara di Nologaten, atau Lembah Kampus UGM), ada yang harus terdaftar MAC address (nomor seri WiFi Card) dan IP address-nya (seperti di kampus, i.e.: AMIKOM, UGM), dan ada pula yang memakai WEP Key (semacam password ke AP) (seperti di RAMA-NET/Netindo Group, Seturan).
Namun biarpun berbeda-beda, ada satu kesamaan keuntungan yang bisa kita dapatkan, sama-sama gratis. Hal ini sangat menguntungkan, khususnya bagi mahasiswa yang senang mendengar kata “gratis”. Kalau beruntung, anda bisa sekaligus menikmati pemandangan atau suasana yang menyenangkan di sekitar hot spot. Kalau ada duit, anda bisa singgah ke café sembari menikmati secangkir kopi, cukup dengan sedikit biaya yang jauh lebih murah daripada yang anda keluarkan untuk menggunakan jasa warnet. Yang paling asyik adalah jika tempat tinggal kita dekat dengan area hot spot. Jika legal, kita bisa memanfaatkan layanan ini kapan pun kita mau. (Hal ini sangat berbeda dengan yang saya rasakan ketika di Bandung –ketika saya PKL di Telkom RisTI selama dua bulanan. Semisal di BTC (Bandung Trade Center), BEC, Cihampelas Walk atau beberapa café lain yang mengharuskan berlangganan ke CBN, Melsa, atau IM2. Kalau ada gratisan, biasanya tiap sekitar tiga menit putus).
Adanya hot spot gratisan ini, bagi kebanyakan mahasiswa seperti saya merupakan berkah tersendiri. Selain hemat biaya, resiko keamanan seperti history, cache, ataupun lupa logout dari suatu website bisa terhindari dengan memakai laptop sendiri. Software aplikasi yang digunakan pun bisa lebih beragam dari software-software yang terinstal di komputer warnet. Bagi entrepreneur, melihat hot spot ini merupakan suatu peluang untuk melebarkan segmentasi pasar atau menjaga loyalitas pelanggan. Dan bagi pedagang komputer, hot spot ini menjadi isu penting untuk menaikkan angka penjualan laptopnya.
Di samping keuntungan dan peluang yang ditawarkan, hot spot juga datang dengan sedikit kerugian dan ancaman. Yang nantinya paling terasa dampaknya adalah bisnis warnet. Seiring terjangkaunya harga laptop, orang-orang yang beralih menggunakan layanan hot spot ini pun akan makin banyak jumlahnya. Namun, hot spot ini pun bukan berarti bebas dari ancaman. Ada segelintir orang yang “kreatif” (baca:kere dan aktif) yang tinggal di sekitar lokasi hot spot, mampu menghadirkan hot spot tadi ke tempat tinggalnya. Tentunya resiko keamanan dan bandwith yang terbuang karena hal ini harus bisa diatasi. Selain hal tersebut, yang mungkin jadi ancaman buat WiFi adalah hadirnya tehnologi baru yang lebih hebat seperti WiMax yang punya daya jangkau hingga 30 km. Jika sudah begini, maka pemerintah dan instansi/asosiasi pengusaha yang terkait harus secepatnya membuat regulasi untuk memanfaatkan keuntungannya dan mengatasi kerugian yang dibawa.
Di balik semuanya, saya yakin nantinya akses internet masyarakat kita bisa merata dan cuma-cuma. Menjadi suatu kebutuhan yang tak terpisahkan dari kehidupan kita. Sama seperti akses acara televisi. Dulu kita wajib membayar “iuran”, namun sekarang kita bisa menonton acara televisi sesuka hati kita berkat kerjasama sponsor yang menjajakan produknya lewat televisi. Pertanyaannya: “Siapkah kita menyaring informasi dari internet tersebut? Khususnya untuk anak-anak dan generasi muda kita?”

04 March 2007

Setitik Nila


Semakin malam obrolan empat orang di pos ronda RT 05 RW X Kelurahan M serasa makin asyik. Paling tidak, itulah cara terbaik mereka yang meronda malam itu untuk menghilangkan kantuk. Sambil sesekali berkelakar dan bermain kartu, mereka satu per satu keliling memantau keadaan sekitarnya. Kegiatan ronda malam yang sudah lama mati kini dijalankan lagi setelah maraknya kemalingan di sekitar Kelurahan M semakin santer akhir-akhir ini. Rumah yang terakhir kemalingan adalah rumah Pak Lurah mereka. Seperangkat home theater dan beberapa peralatan elektronik lainnya ludes dibawa maling. Sejak itulah, Pak Lurah yang juga seorang pengusaha waralaba itu mengeluarkan instruksi untuk mengaktifkan kembali kegiatan ronda malam di masing-masing RT. Alhamdulillah, hampir satu bulan sejak dikeluarkannya instruksi itu belum ada kejadian kemalingan lagi di Kelurahan M.

“Kalo dihitung-hitung, yang paling banyak kemalingannya itu Pak Lurah kita, ya Kang?,” kata Juned pada Kang Amin dengan nada bertanya.

“Dia mah enggak begitu kehilangan. Hasil usaha dagangannya sebulan saja lebih dari cukup untuk membeli lagi barang-barang yang dicuri itu,” timpal Kang Amin yang mulutnya penuh dengan kripik singkong. Ia memang tidak pernah mau rugi soal makanan. Mumpung sekarang bukan gilirannya untuk menyuguhkan makanan. Sebaliknya, ia akan sedikit makan kalau tiba gilirannya. Syukur-syukur masih ada sisa untuk dibawa pulang dan bias untuk cemilan di rumah. Maklum, keluarga Kang Amin termasuk keluarga dengan ekonomi pas-pasan.

“Yang paling kasihan ya Pak Giman itu. Motor kreditan yang baru dipakai tiga hari ikut-ikutan diboyong maling,” Kang Soleh, Ketua Pemuda RT 05, tidak mau ketinggalan memberikan komentar.

“Betul Kang! Padahal kreditannya kan sampai tiga tahun, dan gaji guru SD seperti Pak Giman dan saya ini kan kecil. Paling sisa sedikit setelah semua kebutuhan hidup keluarga tercukupi,” kata Kelik teman seprofesi Pak Giman.

“Eh iya, ngomong-ngomong sampeyan sudah nanya sama Abah belum siapa malingnya dan dimana keberadaannya?,” tanya Juned pada Kang Soleh.


“Sudah, katanya sih pelakunya gerombolan.”

“Abah tidak menyebutkan satu per satu namanya dan dimana mereka sekarang?”

“Tidak.”

“Aneh ya? Tidak biasanya Abah seperti itu. Biasanya Abah kan kalau ditanya barang-barang yang hilang langsung memberi tahu barangnya sekarang ada dimana dan siapa yang mengambil.”

“Iya ya, Ned! Dulu saja ada muridku yang kehilangan tas sekolah, terus dia langsung sowan ke Abah. Abah langsung ngasih tahu kalau tasnya ketinggalan di rumah temannya,” Pak Kelik kembali menimpali.

“Ah… mungkin Abah sudah terlalu capek malam itu. ‘Pasien’-nya kan banyak. Waktu berkunjung ke Abah kemarin, kebetulan aku pasien terakhir malam itu,” Kang Soleh mencoba tetap ber-khusnudzan.

“Iya ya, mungkin betul yang barusan sampeyan katakana. Katanya Abah itu Cuma punya waktu tidur tiga jam setiap harinya,” kata Kang Amin sambil melilitkan sarung di pinggangnya dan menghabiskan kopi yang tersisa di gelas besarnya. Sebentar lagi giliran dia menggantikan Pak Asep yang sedang keliling.

“Coba saja sampeyan hitung sendiri.”

Kang Soleh menyalakan rokok kelintingan-nya, kebiasaan dia sebelum bercerita.

“Pagi hari beliau harus bangun jam empatan untuk memimpin jamaah subuh di masjid pesantrennya. Setelah itu ngajar ngaji santri-santrinya. Selesai pengajian dia ngantor di Madrasah Aliyah sebagai Kepala Madrasah. Itu pun kadang-kadang beliau keluar dari Madrasah untuk mengontrol anak buah di toko meubel dan bengkel mobilnya. Biasanya beliau keluar dari toko atau bengkel ba’da Ashar. Sehabis itu, ngajar ngaji bandongan di Masjid Agung. Maghrib sampai Isya, beliau mengkhususkan diri untuk ber-i’tikaf di Masjid. Tidak boleh diganggu siapapun, apalagi mengurus hal-hal yang bersifat keduniawian. Beliau punya waktu untuk berkumpul dengan keluarga beliau sampai jam sembilan malam. Paling-paling sekedar beristirahat atau makan bersama keluarga. Itu juga kalau beliau tidak ada permintaan untuk mengisi pengajian di suatu acara. Sehabis itu, beliau buka praktek dan menerima tamu-tamu yang mau berkonsultasi padanya, mulai dari permasalahan hukum agama hingga hal-hal seperti pesugihan, mulai orang kere hingga konglomerat atau pejabat teras, sampai jam satu malam.”

“Ck… ck … ck… Luar biasa kegiatan Pak Kyai Tamim alias si Abah itu ya! Sudah kebutuhan dunianya tercukupi, ilmunya pun bermanfaat bagi orang banyak,” sahut Kang Amin spontan.

“Itu juga tidak terlepas dari jasa ayahanda beliau, Kyai Muklas. Konon Abah mewarisi pengikut almarhum Kyai Muklas dari bangsa jin yang jumlahnya ribuan. Jin-jin inilah yang selalu membantu Abah untuk menjawab pertanyaan-pertanyaan pasiennya.”

“Dan saya rasa uang yang beliau terima dari pemberian pasien-pasiennya setiap bulan saja cukup untuk biaya naik haji berapa orang.”

“Itulah rizqi, kita yang sulit-sulit nyari ngalor-ngidul belum tentu dapat, Abah tinggal duduk di rumah, rizqinya malah nyamperin dia,” Juned yang dari tadi Cuma bertanya kini memberikan komentar.

Begitulah, malam itu tidak terasa terlewati dengan obrolan yang mengasyikkan. Tapi seperti malam-malam sebelumnya, sejak kegiatan ronda malam diaktifkan kembali malah tidak ada kejadian apa-apa. Bertentangan dengan ingin terciptanya rasa aman, warga RT 05 dan juga seluruh warga Kelurahan M hanya bisa berharap maling-maling itu melakukan tindakan ceroboh yang bisa membuat mereka tertangkap.

Malam kali ini, rintik-rintik hujan mulai turun sejak ba’da Isya tadi. Namun demikian, tetap saja tak dapat membuat semangat warga yang mendapat giliran tugas ronda malam itu surut. Mereka benar-benar menunaikan tugas mulia itu dengan tingkat kesadaran pribadi yang sangat tinggi. Mereka tidak ingin ada lagi salah satu warganya kehilangan harta benda mereka.

Sampeyan sudah sowan ke Abah lagi, Kang?,” tanya Pak Giman.

“Sudah,” jawab Kang Soleh. Kang Soleh diam sebentar sambil menghirup nafas panjang dan melinting-linting rokoknya. Dia seperti sudah benar-benar kehabisan akal untuk memuaskan pertanyaan itu. Mulutnya hanya mampu mengeluarkan jawaban singkat yang entah sudah diulangnya berapa kali. “Abah masih belum memberikan jawaban pasti, ia hanya berpesan supaya kita bersabar.”

“Saya kok jadi curiga dengan Abah. Tidak biasanya Abah seperti ini!”

“Hus …! Segala bentuk su’udzan itu gak baik Pak,” tukas Kang Soleh. Tiba-tiba memorinya tersangkut kembali dengan kejadian serupa yang pernah dialami Bu Minah, tetangga satu temboknya. “Setahun yang lalu Bu Minah juga pernah kehilangan perhiasannya, namun Abah juga tidak memberikan jawaban pasti.”

“Dan sampai sekarang?,” Pak Giman bertanya lagi. Tapi apapun jawaban yang dikatakan Kang Soleh nantinya, dia hanya mencemaskan motornya yang tidak kunjung kembali.

“Belum ketemu.”

“Ah… lagi pula tak semua jawaban Abah bisa dipastikan kebenarannya. Saya juga punya teman seperti Abah. Tapi jawabannya sering salah. Itu juga tergantung amal dan wiridan yang dilakukan Abah dan tingkat ilmunya serta jin yang menjadi khadam-nya,” komentar Pak De Tomo, sesepuh yang membuat empat lain yang meronda malam itu enggan untuk bermain kartu seperti biasanya. Pak De hanya ingin menenangkan Pak Giman yang jelas masih terlihat belum percaya dan bisa menerima musibah yang menimpanya.

“Maksudnya?”

“Tidak ada satu pun makhluk yang sempurna. Apalagi sempurna perbuatannya. Jin, seperti halnya manusia, juga punya keterbatasan. Meskipun jin itu makhluk ghaib, namun bukan berarti mereka tahu segala sesuatunya. Hanya Allah lah yang Alimul Ghaibi was Syahadah, Yang Maha Mengetahui yang ghaib dan yang nampak.”

Setelah Pak De Tomo selesai berbicara, tiba-tiba Pak Giman menjadi sumringah dan segera bangkit dari duduknya dengan penuh semangat. Bukan karena jawaban Pak De Tomo yang bijak dan menenangkan itu, namun karena terdengar suara yang ditunggu-tunggu Pak Giman selama ini.

“Maling… maling… maling…!,” teriakan itu bergema disertai suara kentongan. Kang Soleh sontak menabuh kentongan di Pos Siskamling dan diikuti keempat kawannya berteriak memberitahukan adanya maling. Para warga sekitar RT 05 berhamburan keluar rumah. Makin lama makin banyak suara itu. Tak mau ketinggalan, para warga dari RT lain pun ikut beramai-ramai turun ke jalan mengikuti sumber suara. Saat yang mereka tunggu selama ini untuk menangkap maling yang selama ini membuat mereka tak bisa tidur tenang sudah datang.

Tiga bayangan hitam berkelebat tak karuan malam itu. Sosok mereka sulit untuk dikenali, karena selain cahaya lampu yang remang-remang, wajah mereka pun tertutup. Namun secara fisik dapat diperkirakan bahwa tiga sosok itu adalah lelaki dan masih muda. Tubuh mereka tegap dan tinggi dengan perawakan yang kekar.

Tiga bayangan hitam yang sudah menyadari diri mereka akan menjadi sasaran amukan warga secepat mungkin ambil langkah seribu dari rumah yang menjadi sasaran perbuatan mereka malam itu. Tubuh mereka yang tinggi besar tak mampu menyembunyikan nyali mereka yang menciut. Debaran jantung mereka terasa lebih keras dan kencang dari biasanya. Adrenalin terasa terpompa deras di bawah kulit mereka. Tak ada waktu untuk berfikir kemana mereka akan lari dan bersembunyi. Mereka benar-benar panik. Barang-barang yang mereka ambil dari rumah korbannya mereka tinggalkan begitu saja. Yang penting bagi mereka saat ini adalah selamat dari kepungan warga.

Warga yang sudah dipenuhi rasa kemarahan dengan penuh semangat mengejar ketiga sosok itu. Semua warga dengan keadaan seadanya turut serta berlari di belakang ketiganya. Ketiga sosok itu terus berlari dengan menghimpun segenap tenaga yang tersisa. Ketika ketiganya sampai di pertigaan jalan, mereka tak bisa berfikir dan bergerak bersama-sama lagi. Mereka berpisah. Yang satu lari ke arah kiri, dua yang lain ke arah kanan. Namun malang bagi ketiganya. Kemanapun mereka lari, di depan mereka sudah menghadang sekelompok massa lainnya yang sudah siap dengan alat pemukul di tangan mereka masing-masing. Ada yang memakai tongkat, sapu, payung, panci, ranting-ranting pohon, bahkan beberapa senjata tajam.

Ketiga bayangan hitam itu sudah terpojok. Tak ada celah jalan ataupun gang-gang sempit untuk melarikan diri. Mereka berdiri merapat di tengah-tengah persimpangan jalan. Lutut mereka gemetaran. Mereka benar-benar takut. Untuk menatap wajah para warga pun mereka tak berani. Keberanian yang tersisa dari mereka hanyalah mengharapkan belas kasihan dan ampunan warga, yang tak mereka berikan pada para korbannya dulu. “Ampun… ampun…,” kata-kata itu diucapkan dengan mimik memelas dan wajah pusat pasi.

Sayangnya permintaan maaf mereka tak diterima warga. Satu pukulan mendarat telak di tengkuk salah satu dari mereka. Pukulan itu langsung diikuti pukulan-pukulan lainnya yang tanpa ampun menghajar wajah dan tubuh mereka malam itu. Amarah dan emosi sudah tak dapat dibendung lagi. Mereka melampiaskan kedongkolan yang sudah lama ditahan. Terlebih lagi Pak Giman. Malam itu dia seperti kerasukan tenaga yang luar biasa. Pukulan dan tendangan yang dilayangkannya menghajar tanpa belas kasihan.

Kang Soleh yang sedari tadi berada di belakang kerumunan massa, berusaha masuk ke tengah-tengah kepungan untuk menghentikan aksi main hakim sendiri itu. Dengan dibantu beberapa pemuda lainnya, akhirnya aksi warga itu dapat dihentikan. Namun malang, salah satu dari maling itu sudah terkapar tak berdaya. Kang Soleh mendekati tubuh itu dan memeriksa detak jantungnya. Dia menghela nafas panjang dan menggelengkan kepalanya. Dia menyesali tindakan warga yang main hakim sendiri, meskipun dia dapat memaklumi dan mengerti tindakan mereka.

Salah satu maling itu telah mati. Kang Soleh mencoba membuka topeng yang menjadi penutup wajah maling itu. Dalam keremangan lampu-lampu jalan malam itu, Kang Soleh berusaha mengenali wajah yang sudah hancur itu. Kang Soleh tersentak kaget ketika berhasil mengenali wajah yang tidak asing baginya.

Astaghfirullahaladzim, taufik dan hidayah-Nya memang sebagian dari rahasia-Nya.”

Setelah mendengar kejadian itu, Kyai Tamim langsung pergi menuju tempat kejadian perkara (TKP). Hatinya galau. Ia berharap berita yang baru didengarnya dari beberapa pemuda yang melapor padanya tidak benar-benar terjadi. Sepanjang jalan ia berusaha menata hatinya berulang kali. Raut gelisah terlihat jelas di wajahnya dan matanya yang mulai berkaca-kaca.

Di TKP sudah terlihat beberapa orang polisi mengamankan kedua tersangka yang masih hidup dan sesosok jasad yang menggeletak tak berdaya itu. Beberapa polisi lain terlihat sedang mengorek keterangan dan menyusun kronologi kejadian. Kyai Tamim segera menghampiri jasad yang sudah tak bernyawa lagi setelah polisi memberinya izin untuk melewati garis batas polisi. Ditatapnya sosok itu. Berulangkali ia berusaha meyakinkan dirinya bahwa yang dilihatnya tidak benar. Namun dilihat berapa kali pun tetap saja ia tak bisa memungkiri bahwa sosok itu benar-benar sudah mati. Dan sosok itu sangatlah dicintainya.Ia menghampiri tubuh itu, kemudian memeluknya. Tangisnya memecah memilukan warga yang masih berdiri di sekitar TKP. Pelan-pelan dipanggilnya beberapa kali nama orang yang sudah mati itu, berharap dia masih bisa mengucapkan sedikit salam perpisahan untuk yang terakhir kalinya, serta sedikit permintaan maaf. Maaf karena tidak bisa mengemban amanat yang telah diberikan Allah kepadanya. Maaf karena dirinya telah gagal mendidiknya. Gagal menjadi ayah bagi jasad itu. Buah hatinya sendiri. Anaknya yang telah terjerumus dalam pergaulan yang salah, dan Kyai Tamim berharap masih bisa membawanya kembali sebelum Allah menakdirkan lain. Namun, tetap saja jasad itu tak bergeming. La haula wala quwata illa billah…

25 Agustus 2004