Penggunaan fungsi Y+Y+Y pada PHP

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

Bagaimana cara membuat fungsi builtin PHP sendiri? Dalam artikel ini Mohammad DAMT menjelaskan langkah-langkahnya.

PHP (PHP: Hypertext Preprocessor) adalah bahasa pemrograman yang hebat. Bahkan konon, kepanjangan PHP yang sebenarnya adalah PHP: Huebate Puoll (PHP: hebatnya poll/full/mentok sampai batas). Namun dibalik kehebatannya itu tentu saja banyak kelemahannya. Dalam artikel ini saya tidak membahas satu-satu kehebatan dan kelemahannya. Saya hanya akan membahas satu sisi dari kelebihan PHP, yaitu kita bisa menambah fungsi-fungsi PHP sendiri dengan cara membuat extension PHP. PHP sebagai salah satu program open source telah membuka lebar kesempatan bagi kita untuk memperluas lagi fitur-fitur yang dimilikinya melalui pembuatan extension.

Extension atau sering juga disebut dengan modul PHP adalah kode program berupa subrutin yang akan dicangkokkan ke dalam tubuh PHP. Fungsi-fungsi yang sering kita gunakan dalam PHP, misalnya fopen(), base64_encode(), atau mysql_query() dan sebagainya sebenarnya merupakan extension PHP. Kita bisa lihat isi perut masing-masing extension di dalam subdirektori ext/ pada direktori kode program PHP.

Pada saat kompilasi, kita memberitahu kompiler untuk mengikutsertakan extension-extension ke dalam PHP. Misalnya pada saat awal tahap kompilasi kita mengetikkan:

Perintah di atas berarti kita akan mengikutsertakan extension MySQL, gd, dan ming ke dalam PHP. Extension-extension inilah yang memungkinkan kita menjalankan fungsi-fungsi MySQL, gd, atau Ming yang bisa kita lihat dalam manual PHP.

Dengan berkembangnya PHP menjadi bahasa serba guna dan tidak hanya untuk keperluan membangun aplikasi Web saja, perluasan fungsi akan semakin terasa diperlukan. Kita nantinya akan semakin terbiasa membuat aplikasi desktop atau berbasis console dengan menggunakan PHP.

Dalam artikel ini saya akan mencontohkan pembuatan extension PHP sederhana yang berisi fungsi-fungsi sederhana, yang akan menunjukkan bagaimana mengembalikan nilai dalam berbagai jenis variabel, mengambil parameter dalam berbagai jenis variabel dan mengakses variabel dari php.ini.

Para pengembang PHP telah berbaik hati dalam menyediakan fasilitas yang cukup lengkap kepada kita untuk membuat tambahan extension baru dengan cepat dan mudah. Mari kita berkunjung ke dalam subdirektori ext/ di direktori kode program PHP.

Di dalam subdirektori inilah kita nanti akan membuat extension PHP baru. Di dalam subdirektori ini pula terdapat sebuah skrip yang telah disediakan untuk membuat extension baru. Sekarang mari kita jalankan skrip tersebut:

Ya, skrip itu akan komplain dengan memberitahukan kita parameter-parameter yang harus kita isi. Yang wajib kita isi hanya satu, yaitu nama extension yang akan kita buat. Nama extension ini harus kita berikan dengan opsi --extname.

Sekarang kita akan membuat extension baru bernama latihan. Caranya dengan mengetikkan:

Skrip ext_skel akan membuat beberapa direktori dan file dan memberikan kita petunjuk singkat langkah selanjutnya dalam pembuatan extension. Sekarang kita sudah memiliki kerangka dasar extension yang barusan dibuatkan oleh skrip ext_skel. Di dalam direktori ext/latihan akan terdapat beberapa file. Namun file-file berikut adalah file-file terpenting:

File-file di atas sudah memiliki beberapa kode dasar yang diperlukan untuk membuat sebuah extension. Tugas kita selanjutnya adalah memodifikasi file-file itu menjadi extension yang lebih berguna.

Pada saat pertama kali menginstal PHP, kita akan melakukan configure. Parameter configure tipikal adalah --with-namaext atau --enable-namaext. Dalam membuat extension, kita perlu memilih bagaimana extension kita akan dikonfigurasikan. Apakah dengan cara --with-latihan atau --enable-latihan? Ini penting sebagai langkah awal pembuatan extension sebagaimana telah diisyaratkan pada butir nomor 4 keluaran dari skrip ext-skel sebelumnya.

Ada panduan singkat untuk masalah ini. Bila extension kita merupakan antarmuka ke pustaka program lain dalam sistem (misalnya untuk binding ke pustaka program tertentu), maka kita harus gunakan --with-latihan. Sebab dengan argumen semacam ini kita bisa menentukan path tempat pustaka program itu berada, yaitu dengan cara:

Namun extension kita ini tidak menggunakan pustaka program khusus, maka kita harus gunakan --enable-latihan. Pilihan kita ini kita wujudkan dalam file config.m4.

Buka dan edit file config.m4 dan buat seperti pada Listing 1. File ini akan digunakan dalam membuat skrip configure nantinya.

Yang khas dalam pemrograman isi perut PHP adalah penggunaan makro yang sering. Sebagaimana kita tahu, makro dalam bahasa C (atau C++) adalah alias beberapa deret perintah yang sering digunakan ke dalam suatu nama tertentu tanpa harus membuatnya sebagai fungsi baru.

Bagi programer C pemula mungkin akan sedikit bingung dalam melihat kode program PHP. Hal ini karena kode program PHP dipenuhi dengan makro yang kadang-kadang sepintas terlihat bukan seperti kode bahasa C yang valid, misalnya:

Dalam kode di atas terdapat penggunaan makro PHP_FE. Perhatikan bahwa di masing-masing baris pada makro tidak terdapat karakter titik-koma sebagaimana dijumpai pada kode program dalam bahasa C yang valid. Bila PHP_FE bukan makro maka tentu saja kode tersebut di atas tidak akan bisa dikompilasi.

Di PHP mulai versi 4, antarmuka pemrograman (API) menggunakan engine Zend. Engine Zend telah menyediakan beberapa fungsi dasar baik berupa fungsi maupun makro. Beberapa fungsi Zend yang akan sering digunakan adalah dalam kategori:

Anda bisa mempelajari semua fungsi-fungsi Zend dalam subdirektori Zend/ dengan melihat langsung ke dalam kode programnya. Dalam modul kita nantinya, akan terlihat bahwa sedemikian sering kita akan mengakses fungsi-fungsi Zend. Kita memang secara sedemikian rupa sebaiknya hanya menggunakan fungsi-fungsi Zend saja, walaupun ada fungsi-fungsi yang memiliki tugas serupa. Misalnya dalam alokasi memori, kita sebaiknya menggunakan fungsi Zend emalloc() daripada fungsi yang biasa kita gunakan, yaitu malloc(). Dengan menggunakan fungsi-fungsi Zend, kita akan mengambil manfaat dari semua kebaikan Zend (dan juga kelemahannya tentu saja). Ini semua akan memudahkan kita pada akhirnya, salah satu contohnya adalah misalnya bila nantinya extension kita akan dikompilasi di platform yang berbeda, maka semuanya akan lebih mudah. Tentunya akan menambah sakit kepala bila kita harus mengubah beberapa perintah yang tidak terdapat pada platform tersebut menjadi perintah-perintah baru. Dengan menggunakan fungsi Zend, singkat kata, kode kita menjadi seportabel PHP4 itu sendiri.

Dalam extension PHP, semua fungsi-fungsi yang dapat diakses publik melalui PHP harus didaftarkan terlebih dahulu. Nama-nama fungsi dimasukkan ke dalam array struktur zend_function_list. Dalam extension latihan, kita memiliki fungsi-fungsi berikut:

Kedua fungsi tersebut harus kita daftarkan terlebih dahulu di dalam file latihan.c dengan:

Perhatikan bahwa array diakhiri dengan {NULL, NULL, NULL}, dan pada tiap-tiap baris tidak terdapat titik-koma (;) untuk mengakhiri suatu baris sebagaimana layaknya kode dalam bahasa C.

Pada file header php_latihan.h semua fungsi tadi juga harus kita deklarasikan dengan makro PHP_FUNCTION. Dalam file tersebut kita lihat deklarasi fungsi akan seperti ini:

Apabila fungsi-fungsi kita tidak didaftarkan, maka fungsi tersebut tidak akan dapat kita gunakan dari kode PHP. Pertama kali rangka extension latihan dibuat, dalam extension ini sudah terdapat sebuah fungsi yang dibuatkan pada awalnya, yaitu fungsi confirm_latihan_compiled(). Fungsi ini hanya akan mengembalikan kalimat berupa ucapan selamat bahwa extension kita telah berhasil dikompilasi.

Semua parameter yang diberikan pada fungsi tidak dideklarasikan pada prototipe fungsi sebagaimana parameter dalam bahasa C. Sebuah fungsi extension memiliki rangka yang sederhana, yaitu:

Semua fungsi, berapapun jumlah parameternya selalu menggunakan rangka prototipe fungsi di atas. Lalu bagaimana parameter dapat kita ambil? Mudah saja. Zend sudah menyiapkan fungsi zend_get_parameters_ex(). Dengan fungsi ini, kita tinggal mengambil parameter dengan menggunakan:

Semua argumen harus merupakan variabel dengan tipe pointer-ke-pointer **zval. Tipe zval merupakan salah satu tipe khusus Zend yang merupakan sebuah struct. Tipe ini dirancang untuk dapat menjadi tipe yang serba guna. Variabel yang menggunakan tipe ini nantinya dapat diset apakah hendak dijadikan long, string, atau bahkan array atau object.

Apabila jumlah parameter berbeda dengan parameter yang didapat, maka fungsi ini akan mengembalikan nilai FAILURE. Langkah yang baik apabila kita mendapatkan FAILURE adalah dengan memanggil makro WRONG_PARAM_COUNT yang akan menuliskan pesan error bahwa argumen yang diterima kurang (atau lebih).

Variabel yang telah diambil dengan fungsi zend_get_parameters_ex() selanjutnya perlu kita olah lagi dengan mengkonversinya ke dalam tipe yang kita inginkan. Apabila kita mengambil nilai integer maka kita harus mengkonversinya menjadi integer. Ada beberapa fungsi Zend yang telah disediakan, yaitu:

Kesemua fungsi di atas tidak mengembalikan nilai apapun, mereka berfungsi untuk menyiapkan variabel agar dapat mengembalikan nilai dalam tipe yang diinginkan. Tadi disebutkan bahwa tipe variabel dengan jenis ini bisa ditentukan dengan menset salah satu anggota structnya. Nah fungsi-fungsi di atas melakukan hal tersebut. Pada masing-masing fungsi di atas, sebenarnya akan menyiapkan tipe variabel dan isi nilai aslinya akan disimpan ke dalam anggota struct:

Tugas kita selanjutnya hanyalah mengambil nilai variabel tersebut langsung dari dalam struct. Cara mengambil nilainya juga mudah. Kita bisa langsung mengambil nilai dengan menggunakan referensi variabel seperti di atas, dan bagi Anda yang tidak senang mengetikkan kode-kode arg->value.xxx.yyy bisa juga menggunakan makro berikut:

Tentu saja, variabel nilai harus disesuaikan tipenya dengan fungsi/makro yang hendak kita gunakan. O ya, bergantung pada tipe variabel yang kita tentukan (dalam contoh di atas, saya menggunakan tipe **zval), ada juga berbagai varian untuk fungsi-fungsi dan makro-makro di atas. Anda bisa melihat-lihat isi extension lain di dalam subdirektori ext/ untuk mendalaminya.

Dalam fungsi latihan_ambilinteger($arg1, $arg2) kita mengambil dua buah argumen integer sebagai parameter dan akan mengalikan keduanya. Potongan kode program berikut akan mengambil nilai dari parameter-parameter arg1 dan arg2 dan memasukkannya ke dalam variabel internal yang sudah kita siapkan, yaitu angka1 dan angka2.

Kita bisa lihat penggunaan yang lain dari fungsi zend_get_parameters_ex() dalam Listing 2 yang digunakan pada masing-masing fungsi dalam extension latihan.

Zend telah menyiapkan beberapa makro untuk mengakses variabel yang disebutkan di dalam file konfigurasi php.ini. Apabila perlu, extension kita juga diperbolehkan memiliki jatah ruangan tersendiri dalam file php.ini. Untuk menggunakan fasilitas ini, kita perlu menyediakan variabel yang bersifat global dalam extension. Variabel ini harus kita deklarasikan dalam lingkup makro ZEND_BEGIN_MODULE_GLOBALS(latihan) dan ZEND_END_MODULE_GLOBALS(latihan) dalam file php_latihan.h. Dan jangan lupa di dalam file latihan.c kita juga perlu memanggil makro ZEND_DECLARE_MODULE_GLOBALS(latihan).

Dalam extension latihan, kita memiliki dua buah variabel yang kita letakkan dalam file php.ini, yaitu angka yang bertipe integer dan kata yang bertipe string. Dalam file latihan.c kita mendeklarasikan penggunaan variabel ini dengan:

latihan.angka adalah nama variabel yang berlaku dalam php.ini. Variabel ini akan diwakili oleh variabel angka yang berlaku dalam keseluruhan extension. Jadi nama variabel dalam php.ini dan dalam program boleh berbeda. Argumen kedua adalah nilai default variabel kita. Pada angka defaultnya adalah 21. Perhatikan bahwa walaupun angka bertipe integer, pada php.ini tetap kita perlakukan sebagai string. Semua perubahan yang terjadi pada variabel latihan.angka akan ditangani oleh fungsi internal OnUpdateInt yang sudah disediakan oleh Zend. Bila kita menginginkan adanya pemrosesan tertentu pada variabel dalam php.ini kita boleh mendeklarasikan fungsi sendiri. Anda bisa lihat contoh penggunaan fungsi sendiri dalam pengolahan variabel php.ini ini dalam extension lain dalam subdirektori ext/.

Lalu di dalam kode extension, kita tidak boleh langsung mengakses variabel global tadi. Kita harus menggunakan makro LATIHAN_G(angka) untuk mengakses variabel angka. Makro LATIHAN_G(namavariabel) telah disediakan untuk mengakses semua variabel global yang sudah dideklarasikan di dalam php_latihan.h.

Kita dapat mengembalikan nilai dari fungsi PHP kita dengan cara menggunakan beberapa makro yang telah disediakan Zend. Makro-makro tersebut di antaranya adalah:

Ok, sekarang bagaimana caranya mengembalikan nilai berupa array atau object ? Mudah saja. Makro-makro di atas sebenarnya memodifikasi suatu variabel khusus bernama return_value yang berupa variabel Zend. Dia memiliki sifat yang mirip dengan variabel-variabel yang telah kita gunakan sebagai parameter fungsi. Artinya, variabel return_value ini merupakan sebuah struct yang isi dan tipenya bisa kita tentukan dengan menset anggota-anggota structnya (Masih ingat kan cara mengakses isi nilai dari parameter langsung dari struct?). Variabel return_value inilah yang sebenarnya selalu dikembalikan oleh sebuah fungsi PHP dalam extension.

Dalam file latihan.c dicontohkan fungsi-fungsi yang mengembalikan array dan object. Anda bisa lihat kode dalam fungsi tersebut rupanya tidak serumit yang kita bayangkan.

Untuk membangun extension agar dapat dikompilasi sudah disinggung sedikit pada awal artikel (pada output skrip ext_skel). Langkah-langkah selanjutnya adalah:

Pada langkah ketiga kita gunakan --enable-latihan=shared tujuannya agar hasil kompilasi nantinya dibuat berupa shared library. Setelah make selesai, file akhirnya adalah ext/latihan/.libs/latihan.so dan kemudian akan disalin ke dalam direktori modules/. Kenapa kita gunakan shared library? tujuannya adalah untuk memudahkan kita dalam menguji extension kita. Bila ada kesalahan, maka proses make hanya membangun extension kita saja, tidak membangun keseluruhan program PHP. Nanti bila kita sudah yakin bahwa tidak ada kesalahan lagi, barulah kita gunakan --enable-latihan (tanpa shared). Setelah ini, extension kita akan dimasukkan ke dalam PHP sebagai fungsi builtin.

Untuk menguji extension kita, sudah disediakan file latihan.php. Isi file ini adalah program sederhana dalam PHP yang memanggil semua fungsi yang disediakan dalam latihan.c. Program ini dirancang untuk dapat diuji dengan meload extension kita dalam bentuk shared library. Letakkan file latihan.so dalam lokasi yang sama dengan file latihan.php. Jangan lupa di php.ini pada direktif extension_dir perlu diberi nilai:

Tujuannya agar program PHP kita akan meload shared library dalam lokasi yang sama. Namun bila Anda menginginkan lain, silakan taruh file latihan.so di lokasi yang Anda tentukan dalam direktif extension_dir pada php.ini.

Program PHP kita pertama kali akan meload extension dengan perintah dl(). Kemudian ia akan melanjutkan dengan memanggil semua fungsi-fungsi extension kita. Sekarang mari kita tes extension kita dari browser (letakkan dulu latihan.so dan latihan.php pada direktori Web Anda) atau langsung dari shell seperti ini:

Selamat! Extension Anda sudah jadi. Untuk melakukan tes lain kita bisa menambahkan perintah-perintah lain ataupun sekedar phpinfo(). Perintah phpinfo() akan mengeluarkan seperti ditunjukkan pada Gambar 1. Dari sini kita juga bisa melihat isi konfigurasi extension kita pada php.ini. Coba Anda tambahkan baris berikut pada php.ini dan lihat lagi output phpinfo():

Anda bisa mengembangkan extension PHP Anda sendiri lebih lanjut. Ada banyak hal yang bisa Anda lakukan. Anda boleh membuat antarmuka ke suatu pustaka program tertentu (seperti misalnya antarmuka ke MySQL, MSSQL, dan sebagainya), atau juga membuat fungsi-fungsi sendiri yang saat ini tidak terdapat dalam PHP (misalnya membuat fungsi-fungsi grafik lanjutan, membuat film, dan sebagainya). Atau juga sekedar membuat fungsi-fungsi Anda agar tidak dapat diintip orang. Perlu juga diingat bahwa terdapat lebih dari satu varian makro dan variabel yang telah dijelaskan di atas. Setelah membaca artikel ini Anda jangan harapkan langsung mengerti sifat-sifat dan perilaku sebuah extension PHP (kalau langsung mengerti ya syukur). Anda masih harus menggali lagi lebih dalam fungsi-fungsi API Zend dan contoh-contoh extension lain dalam subdirektori ext/.

Mohammad DAMT, atau mdamt, sudah malang-melintang dalam dunia open source selama beberapa tahun. Dalam menyambut bulan puasa, apa yang dilakukannya? Ternyata malah menyempatkan diri membuat situs triple eks. Silakan [atau jangan, bergantung pada ingin batal atau tidak] melihat halaman berikut: aksi.mdamt.net/main.xxx.