Dengan menggunakan fitur bahasa baru PHP V5, pemeliharaan dan keandalan kode dapat ditingkatkan secara signifikan. Dengan membaca artikel ini, Anda akan mempelajari cara memanfaatkan fitur-fitur baru ini untuk memigrasikan kode yang dikembangkan di PHP V4 ke PHP V5.
PHP V5 telah membuat perbaikan signifikan berdasarkan PHP V4. Fitur bahasa baru mempermudah pembuatan perpustakaan kelas yang andal dan memeliharanya. Selain itu, menulis ulang pustaka standar membantu menjadikan PHP lebih selaras dengan idiom Web lainnya, seperti bahasa pemrograman Java™. Mari kita lihat beberapa fitur berorientasi objek baru PHP dan pelajari cara memigrasi kode PHP V4 yang ada ke PHP V5.
Pertama, mari kita lihat bagaimana fitur bahasa baru dan pencipta PHP telah mengubah cara objek dibuat dengan PHP V4. Ide dengan V5 adalah untuk menciptakan bahasa berkekuatan industri untuk pengembangan aplikasi Web. Itu berarti memahami keterbatasan PHP V4, kemudian mengekstraksi arsitektur bahasa yang dikenal baik dari bahasa lain (seperti Java, C#, C++, Ruby, dan Perl) dan menggabungkannya ke dalam PHP.
Fitur baru yang pertama dan paling penting adalah perlindungan akses untuk metode kelas dan variabel instan - kata kunci publik, dilindungi, dan pribadi. Fitur baru ini memungkinkan desainer kelas untuk mempertahankan kendali atas properti intrinsik suatu kelas sambil memberi tahu pengguna kelas kelas mana yang dapat diakses dan mana yang tidak.
Di PHP V4, semua kode bersifat publik. Di PHP V5, desainer kelas dapat mendeklarasikan kode mana yang terlihat oleh dunia luar (publik) dan kode mana yang hanya terlihat di dalam kelas (pribadi) atau hanya untuk subkelas dari kelas tersebut (dilindungi). Tanpa kontrol akses ini, pengembangan kode dalam tim besar atau pendistribusian kode sebagai perpustakaan akan terhambat karena pengguna kelas tersebut cenderung menggunakan metode atau kode akses yang salah yang seharusnya menjadi variabel anggota pribadi.
Fitur baru yang besar lainnya adalah antarmuka kata kunci dan abstrak, yang memungkinkan pemrograman kontrak. Pemrograman kontrak berarti satu kelas memberikan kontrak ke kelas lain - dengan kata lain: "Inilah yang akan saya lakukan, dan Anda tidak perlu tahu cara melakukannya." Semua kelas yang mengimplementasikan antarmuka mematuhi kontrak ini. Semua pengguna antarmuka setuju untuk hanya menggunakan metode yang ditentukan dalam antarmuka. Kata kunci abstract membuat bekerja dengan antarmuka menjadi sangat mudah, seperti yang akan saya jelaskan nanti.
Dua fitur utama ini - kontrol akses dan pemrograman kontrak - memungkinkan tim pembuat kode yang besar bekerja lebih lancar dengan basis kode yang besar. Fitur-fitur ini juga memungkinkan IDE menyediakan serangkaian fitur cerdas bahasa yang lebih kaya. Artikel ini tidak hanya membahas beberapa masalah migrasi, namun juga menjelaskan cara menggunakan fitur bahasa utama baru ini.
Kontrol Akses
Untuk mendemonstrasikan fitur bahasa baru, saya menggunakan kelas bernama Konfigurasi. Kelas sederhana ini berisi item konfigurasi untuk aplikasi Web - misalnya, jalur ke direktori gambar. Idealnya, informasi ini berada dalam file atau database. Listing 1 menunjukkan versi yang disederhanakan.
Daftar 1. access.php4
<?php
Konfigurasi kelas
{
var $_items = array();
fungsi Konfigurasi() {
$this->_items[ 'imgpath' ] = 'gambar';
}
fungsi dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
$c = Konfigurasi baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Ini adalah kelas PHP V4 yang sepenuhnya ortodoks. Variabel anggota menyimpan daftar item konfigurasi, konstruktor memuat item, dan metode akses bernama get() mengembalikan nilai item.
Setelah skrip dijalankan, kode berikut akan muncul di baris perintah:
%php access.php4
gambar
%
sangat bagus! Hasil ini berarti kode berjalan normal dan nilai item konfigurasi imgpath disetel dan dibaca secara normal.
Langkah pertama dalam mengonversi kelas ini ke PHP V5 adalah mengganti nama konstruktornya. Di PHP V5, metode inisialisasi suatu objek (konstruktor) disebut __construct. Perubahan kecil ini ditunjukkan di bawah.
Daftar 2. access1.php5
<?php
Konfigurasi kelas
{
var $_item = array();
fungsi __konstruksi() {
$this->_items[ 'imgpath' ] = 'gambar';
}
fungsi dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
$c = Konfigurasi baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Perubahan kali ini tidak besar. Baru saja pindah ke konvensi PHP V5. Langkah selanjutnya adalah menambahkan kontrol akses ke kelas untuk memastikan bahwa pengguna kelas tidak dapat langsung membaca dan menulis variabel anggota $_items. Perubahan ini ditunjukkan di bawah ini.
Daftar 3.access2.php5
<?php
Konfigurasi kelas
{
pribadi $_items = array();
fungsi publik __construct() {
$this->_items[ 'imgpath' ] = 'gambar';
}
fungsi publik dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
$c = Konfigurasi baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Jika pengguna objek ini mengakses larik item secara langsung, akses akan ditolak karena larik ditandai pribadi. Untungnya, pengguna telah menemukan bahwa metode get() memberikan izin membaca yang sangat disukai.
Untuk mengilustrasikan cara menggunakan izin yang dilindungi, saya memerlukan kelas lain, yang harus mewarisi dari kelas Konfigurasi. Saya memanggil kelas itu DBConfiguration dan berasumsi bahwa kelas tersebut akan membaca nilai konfigurasi dari database. Pengaturan ini ditunjukkan di bawah.
Daftar 4.access3.php
<?php
Konfigurasi kelas
{
dilindungi $_items = array();
fungsi publik __construct() {
$ini->beban();
}
fungsi yang dilindungi memuat() {} }
fungsi publik dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
kelas DBConfiguration memperluas Konfigurasi
{
fungsi yang dilindungi memuat() {
$this->_items[ 'imgpath' ] = 'gambar';
}
}
$c = Konfigurasi DB baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Daftar ini menunjukkan penggunaan yang benar dari kata kunci yang dilindungi. Kelas dasar mendefinisikan metode bernama load(). Subkelas dari kelas ini akan mengganti metode load() untuk menambahkan data ke tabel item. Metode load() bersifat internal pada kelas dan subkelasnya, sehingga metode ini tidak terlihat oleh semua konsumen eksternal. Jika semua kata kunci bersifat pribadi, metode load() tidak dapat diganti.
Saya tidak terlalu menyukai desain ini, tetapi saya memilihnya karena saya harus memberikan akses kelas DBConfiguration ke array item. Saya ingin terus mempertahankan susunan item sepenuhnya oleh kelas Konfigurasi, sehingga saat subkelas lain ditambahkan, kelas tersebut tidak perlu mengetahui cara memelihara susunan item. Saya membuat perubahan berikut.
Daftar 5.access4.php5
<?php
Konfigurasi kelas
{
pribadi $_items = array();
fungsi publik __construct() {
$ini->beban();
}
fungsi yang dilindungi memuat() {} }
fungsi terlindungi tambahkan( $kunci, $nilai ) {
$ini->_item[ $kunci ] = $nilai;
}
fungsi publik dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
kelas DBConfiguration memperluas Konfigurasi
{
fungsi yang dilindungi memuat() {
$ini->tambahkan( 'imgpath', 'gambar' );
}
}
$c = Konfigurasi DB baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Array item sekarang bisa bersifat pribadi karena subkelas menggunakan metode add() yang dilindungi untuk menambahkan item konfigurasi ke daftar. Kelas Konfigurasi dapat mengubah cara menyimpan dan membaca item konfigurasi tanpa memperhatikan subkelasnya. Selama metode load() dan add() dijalankan dengan cara yang sama, subkelas seharusnya tidak memiliki masalah.
Bagi saya, kontrol akses tambahan adalah alasan utama untuk mempertimbangkan pindah ke PHP V5. Apakah hanya karena Grady Booch mengatakan bahwa PHP V5 adalah salah satu dari empat bahasa berorientasi objek utama? Tidak, karena saya pernah menerima tugas untuk memelihara kode 100KLOC C++ di mana semua metode dan anggota didefinisikan sebagai publik. Saya membutuhkan waktu tiga hari untuk membersihkan definisi ini, dan dalam prosesnya, saya secara signifikan mengurangi jumlah kesalahan dan meningkatkan kemudahan pemeliharaan. Mengapa? Karena tanpa kontrol akses, tidak mungkin mengetahui bagaimana suatu objek menggunakan objek lain, dan tidak mungkin melakukan perubahan apa pun tanpa mengetahui kendala apa yang harus diatasi. Dengan C++, setidaknya saya masih memiliki kompiler yang tersedia. PHP tidak disertai kompiler, jadi jenis kontrol akses ini menjadi lebih penting.
Pemrograman Kontrak
Fitur penting berikutnya yang dapat dimanfaatkan ketika bermigrasi dari PHP V4 ke PHP V5 adalah dukungan untuk pemrograman kontrak melalui antarmuka, kelas abstrak, dan metode. Listing 6 menunjukkan versi kelas Konfigurasi di mana pembuat kode PHP V4 mencoba membangun antarmuka dasar tanpa menggunakan kata kunci antarmuka sama sekali.
Listing 6.interface.php4
<?php
Konfigurasi I kelas
{
fungsi dapatkan( $kunci ) {}
}
Konfigurasi kelas memperluas IConfiguration
{
var $_items = array();
fungsi Konfigurasi() {
$ini->beban();
}
beban fungsi() {} }
fungsi dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
kelas DBConfiguration memperluas Konfigurasi
{
beban fungsi() {
$this->_items[ 'imgpath' ] = 'gambar';
}
}
$c = Konfigurasi DB baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Daftar dimulai dengan kelas IConfiguration kecil yang mendefinisikan semua antarmuka yang disediakan oleh kelas Konfigurasi atau kelas turunan. Antarmuka ini akan menentukan kontrak antara kelas dan semua penggunanya. Kontrak menyatakan bahwa semua kelas yang mengimplementasikan IConfiguration harus dilengkapi dengan metode get() dan semua pengguna IConfiguration harus bersikeras untuk hanya menggunakan metode get().
Kode di bawah ini dijalankan di PHP V5, namun lebih baik menggunakan sistem antarmuka yang disediakan seperti gambar di bawah ini.
Listing 7.interface1.php5
<?php
konfigurasi antarmuka
{
fungsi dapatkan( $kunci );
}
Konfigurasi kelas mengimplementasikan IConfiguration
{
...
}
kelas DBConfiguration memperluas Konfigurasi
{
...
}
$c = Konfigurasi DB baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Di satu sisi, pembaca dapat memahami status berjalan dengan lebih jelas; di sisi lain, satu kelas dapat mengimplementasikan banyak antarmuka. Listing 8 menunjukkan cara memperluas kelas Konfigurasi untuk mengimplementasikan antarmuka Iterator, yang merupakan antarmuka internal untuk PHP.
Listing 8.interface2.php5
<?php
konfigurasi antarmuka {
...
}
Konfigurasi kelas mengimplementasikan IConfiguration, Iterator
{
pribadi $_items = array();
fungsi publik __construct() {
$ini->beban();
}
fungsi yang dilindungi memuat() {} }
fungsi terlindungi tambahkan( $kunci, $nilai ) {
$ini->_item[ $kunci ] = $nilai;
}
fungsi publik dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
fungsi publik mundur() { reset($ini->_item);
fungsi publik saat ini() { kembalikan arus($ini->_item);
kunci fungsi publik() { kunci kembali($ini->_item);
fungsi publik berikutnya() { kembali berikutnya($ini->_item);
fungsi publik valid() { kembali ( $ini->saat ini() !== salah }
}
kelas DBConfiguration memperluas Konfigurasi {
...
}
$c = Konfigurasi DB baru();
foreach( $c sebagai $k => $v ) { echo( $k." = ".$v."n" }
?>
Antarmuka Iterator memungkinkan kelas mana pun tampak seperti serangkaian konsumennya. Seperti yang Anda lihat di akhir skrip, Anda dapat menggunakan operator foreach untuk mengulangi semua item konfigurasi di objek Konfigurasi. PHP V4 tidak memiliki fungsi ini, tetapi Anda dapat menggunakan fungsi ini dengan berbagai cara dalam aplikasi Anda.
Keuntungan dari mekanisme antarmuka adalah kontrak dapat dengan cepat disatukan tanpa harus menerapkan metode apa pun. Tahap terakhir adalah mengimplementasikan antarmuka, di mana Anda harus mengimplementasikan semua metode yang ditentukan. Fitur baru bermanfaat lainnya di PHP V5 adalah kelas abstrak, yang memudahkan implementasi bagian inti antarmuka dengan kelas dasar dan kemudian menggunakan antarmuka tersebut untuk membuat kelas entitas.
Kegunaan lain dari kelas abstrak adalah untuk membuat kelas dasar untuk beberapa kelas turunan dimana kelas dasar tidak pernah dipakai. Misalnya, ketika DBConfiguration dan Configuration ada pada saat yang sama, hanya DBConfiguration yang dapat digunakan. Kelas Konfigurasi hanyalah kelas dasar - kelas abstrak. Oleh karena itu, Anda dapat memaksakan perilaku ini menggunakan kata kunci abstrak seperti yang ditunjukkan di bawah ini.
Daftar 9. abstract.php5
<?php
Konfigurasi kelas abstrak
{
dilindungi $_items = array();
fungsi publik __construct() {
$ini->beban();
}
fungsi yang dilindungi abstrak load();
fungsi publik dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
kelas DBConfiguration memperluas Konfigurasi
{
fungsi yang dilindungi memuat() {
$this->_items[ 'imgpath' ] = 'gambar';
}
}
$c = Konfigurasi DB baru();
echo( $c->dapatkan( 'imgpath' )."n" );
?>
Sekarang, semua upaya untuk membuat instance objek bertipe Konfigurasi akan error karena sistem menganggap kelas tersebut abstrak dan tidak lengkap.
Metode dan anggota statis
Fitur penting baru lainnya di PHP V5 adalah dukungan untuk anggota dan metode statis di kelas. Dengan menggunakan fungsi ini, Anda dapat menggunakan pola tunggal yang populer. Pola ini ideal untuk kelas Konfigurasi karena aplikasi hanya boleh memiliki satu objek konfigurasi.
Listing 10 menunjukkan versi PHP V5 dari kelas Konfigurasi sebagai singleton.
Daftar 10. static.php5
<?php
Konfigurasi kelas
{
pribadi $_items = array();
statis pribadi $_instance = null;
fungsi publik statis get() {
jika ( mandiri::$_instance == null )
self::$_instance = Konfigurasi baru();
kembalikan diri::$_instance;
}
fungsi pribadi __construct() {
$this->_items[ 'imgpath' ] = 'gambar';
}
fungsi publik __dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
echo( Konfigurasi::get()->{ 'imgpath' }."n" );
?>
Kata kunci statis memiliki banyak kegunaan. Pertimbangkan untuk menggunakan kata kunci ini ketika Anda perlu mengakses beberapa data global untuk semua objek dengan tipe yang sama.
Metode Ajaib
Fitur baru lainnya yang besar di PHP V5 adalah dukungan untuk metode ajaib, yang memungkinkan objek mengubah antarmuka objek dengan cepat - misalnya, menambahkan variabel anggota untuk setiap item konfigurasi di objek Konfigurasi. Tidak perlu menggunakan metode get(), cukup cari item tertentu dan perlakukan sebagai array, seperti yang ditunjukkan di bawah ini.
Daftar 11. magic.php5
<?php
Konfigurasi kelas
{
pribadi $_items = array();
fungsi __konstruksi() {
$this->_items[ 'imgpath' ] = 'gambar';
}
fungsi __dapatkan( $kunci ) {
kembalikan $ini->_item[ $kunci ];
}
}
$c = Konfigurasi baru();
echo( $c->{ 'imgpath' }."n" );
?>
Dalam contoh ini, saya membuat metode __get() baru yang dipanggil setiap kali pengguna mencari variabel anggota pada objek. Kode dalam metode ini kemudian akan menggunakan array item untuk menemukan nilai dan mengembalikan nilai tersebut seolah-olah ada variabel anggota di sana khusus untuk kata kunci tersebut. Dengan asumsi bahwa objeknya adalah array, di akhir skrip Anda dapat melihat bahwa menggunakan objek Konfigurasi semudah menemukan nilai imgpath.
Saat bermigrasi dari PHP V4 ke PHP V5, Anda harus menyadari fitur-fitur bahasa yang sama sekali tidak tersedia di PHP V4, dan Anda harus memvalidasi ulang kelas untuk melihat bagaimana mereka dapat digunakan.
Pengecualian
akhirnya mengakhiri artikel ini dengan memperkenalkan mekanisme pengecualian baru di PHP V5. Pengecualian memberikan cara berpikir yang benar-benar baru tentang penanganan kesalahan. Semua program pasti menghasilkan kesalahan - file tidak ditemukan, kehabisan memori, dll. Jika pengecualian tidak digunakan, kode kesalahan harus dikembalikan. Silakan lihat kode PHP V4 di bawah ini.
Daftar 12. file.php4
<?php
fungsi parseLine( $l )
{
// ...
kembali array('kesalahan' => 0,
data => array() // data di sini
);
}
fungsi readConfig( $jalur )
{
jika ( $path == null ) kembalikan -1;
$fh = fopen( $jalur, 'r' );
jika ( $fh == null ) kembalikan -2;
sementara( !feof( $fh ) ) {
$l = fget( $fh );
$ec = parseLine( $l );
jika ( $ec['error'] != 0 ) mengembalikan $ec['error'];
}
fclose( $fh );
kembali 0;
}
$e = readConfig( 'konfigurasisaya.txt' );
jika ( $e != 0 )
echo("Terjadi kesalahan (".$e.")n" );
?>
Kode I/O file standar ini akan membaca file, mengambil beberapa data, dan mengembalikan kode kesalahan jika ditemukan kesalahan. Saya punya dua pertanyaan tentang skrip ini. Yang pertama adalah kode kesalahan. Apa arti kode kesalahan ini? Untuk mengetahui arti dari kode kesalahan ini, Anda harus membuat sistem lain untuk memetakan kode kesalahan ini menjadi string yang bermakna. Masalah kedua adalah hasil pengembalian parseLine sangat rumit. Saya hanya membutuhkannya untuk mengembalikan data, tetapi sebenarnya harus mengembalikan kode kesalahan dan data. Kebanyakan insinyur (termasuk saya sendiri) sering menjadi malas dan hanya mengembalikan data dan mengabaikan kesalahan karena kesalahan sulit untuk dikelola.
Listing 13 menunjukkan betapa jelasnya kode tersebut saat menggunakan pengecualian.
Daftar 13. file.php5
<?php
fungsi parseLine( $l )
{
// Parsing dan lemparan serta pengecualian ketika tidak valid
kembalikan array(); //data
}
fungsi readConfig( $jalur )
{
jika ( $jalur == nol )
melempar Pengecualian baru( 'argumen buruk' );
$fh = fopen( $path, 'r' );
jika ( $fh == nol )
melempar Pengecualian baru( 'tidak dapat membuka file' );
while( !feof( $fh ) ) {
$l = fget( $fh );
$ec = parseLine( $l );
}
fclose( $fh );
}
mencoba {
readConfig('konfigurasisaya.txt' );
} tangkapan(Pengecualian $e) {
gema($e);
}
?>
Saya tidak perlu khawatir tentang kode kesalahan karena pengecualian berisi teks deskriptif untuk kesalahan tersebut. Saya juga tidak perlu memikirkan cara melacak kode kesalahan yang dikembalikan dari parseLine karena fungsinya hanya akan memunculkan kesalahan jika terjadi. Tumpukannya meluas ke blok coba/tangkap terdekat, yang ada di bagian bawah skrip.
Pengecualian akan merevolusi cara Anda menulis kode. Daripada pusing memikirkan kode kesalahan dan pemetaan, Anda bisa fokus pada kesalahan yang ingin Anda tangani. Kode seperti itu lebih mudah dibaca, dipelihara, dan menurut saya bahkan mendorong Anda untuk menambahkan penanganan kesalahan, karena biasanya memberikan keuntungan.
Kesimpulan
Fitur berorientasi objek baru dan penambahan penanganan pengecualian memberikan alasan kuat untuk memigrasikan kode dari PHP V4 ke PHP V5. Seperti yang Anda lihat, proses upgrade tidak sulit. Sintaks yang diperluas ke PHP V5 terasa seperti PHP. Ya, sintaksis ini berasal dari bahasa seperti Ruby, tapi menurut saya keduanya bekerja sama dengan sangat baik. Dan bahasa-bahasa ini memperluas cakupan PHP dari bahasa scripting untuk situs kecil menjadi bahasa yang dapat digunakan untuk menyelesaikan aplikasi tingkat perusahaan.