Teks/Dikompilasi oleh Zhu Xianzhong
1. Pendahuluan
Untungnya, teknologi kelebihan beban objek diperkenalkan di PHP 5.0. Artikel ini akan mengeksplorasi kemungkinan membebani metode __call(), __set() dan __get() secara berlebihan. Setelah pengenalan singkat tentang teori kelebihan beban, kita akan langsung ke topik melalui dua contoh: contoh pertama adalah mengimplementasikan kelas penyimpanan persisten; contoh kedua adalah menemukan cara untuk mengimplementasikan pengambil/penyetel dinamis.
2. Apa yang dimaksud dengan kelebihan beban objek?
Ketika berbicara tentang kelebihan beban objek di PHP, kita harus membedakan dua jenis:
·Metode kelebihan beban
· Kelebihan atribut
Dalam kasus kelebihan metode, kita harus mendefinisikan metode ajaib __call(), yang akan mengimplementasikan panggilan umum A ke metode yang tidak ditentukan di kelas yang bersangkutan. Metode umum ini dipanggil hanya ketika Anda ingin mengakses metode yang tidak ditentukan di kelas. Tanpa kelebihan metode, contoh berikut akan menyebabkan PHP menampilkan pesan kesalahan fatal: Panggil ke metode yang tidak terdefinisi ThisWillFail::bar() di/some/directory/example.php pada baris 9 dan batalkan eksekusi program:
< ?php
kelas ThisWillFail {
fungsi publik foo() {
kembalikan "Halo Dunia!";
}
}
$kelas = baru ThisWillFail;
$kelas->bar();
?>
Dengan bantuan metode kelebihan beban, kode dapat menangkap panggilan ini dan menanganinya dengan baik.
Kelebihan properti mirip dengan kelebihan metode. Dalam hal ini, kelas mengalihkan (juga disebut proksi) operasi baca/tulis ke properti kelas yang tidak didefinisikan secara eksplisit di kelas. Metode khusus di sini adalah __set() dan __get(). Tergantung pada tingkat pelaporan kesalahan, penerjemah PHP biasanya akan mengeluarkan pemberitahuan ketika mengakses properti yang tidak ditentukan, atau menunda dan berpotensi menentukan variabel. Jika Anda menggunakan kelebihan atribut, penerjemah dapat memanggil __set() saat menyetel atribut yang tidak ditentukan, dan memanggil __get() saat mengakses nilai atribut yang tidak ditentukan.
Singkatnya, penggunaan teknologi kelebihan muatan dapat mempersingkat waktu pengembangan perangkat lunak ketika menggunakan bahasa dinamis seperti PHP.
Pada titik ini, teori diperkenalkan, dan pengkodean spesifik dianalisis di bawah.
3. Contoh kelas penyimpanan persisten
Kode berikut mengimplementasikan kelas penyimpanan persisten yang disebutkan di atas dengan kurang dari 50 baris kode PHP dengan menggunakan teknologi kelebihan atribut. Istilah persisten berarti bahwa kelas dapat mendeskripsikan elemen dari struktur data dan tetap tersinkronisasi dengan sistem penyimpanan yang mendasarinya. Dalam istilah pengkodean, kode eksternal dapat menggunakan kelas untuk memilih baris dari tabel database. Dengan cara ini, ketika program sedang berjalan, Anda dapat langsung mengakses atribut kelas untuk memanipulasi elemen dalam baris (baca/ambil). Di akhir skrip, PHP akan bertanggung jawab untuk mengirimkan data baris yang diperbarui kembali ke database.
Mempelajari kode berikut dengan cermat akan membantu Anda memahami apa yang dimaksud dengan kelebihan beban atribut.
<?php
//Muat <a href=" http://pear.php.net/package/DB/ "> Paket DB</a> PEAR
require_once "DB.php";
kelas Bertahan {
pribadi $data = array();
pribadi $tabel = "pengguna";
fungsi publik __konstruksi($pengguna) {
$ini->dbh = DB::Connect("mysql://pengguna:password@localhost/database");
$query = "PILIH id, nama, email, negara DARI " .
$ini->tabel . " DIMANA nama = ?";
$ini->data = $ini->dbh->getRow($query, array($pengguna),
DB_FETCHMODE_ASSOC);
}
fungsi publik __mendapatkan($anggota) {
if (isset($ini->data[$anggota])) {
kembalikan $ini->data[$anggota];
}
}
fungsi publik __set($anggota, $nilai) {
//ID kumpulan data bersifat read-only if ($member == "id") {
kembali;
}
if (isset($ini->data[$anggota])) {
$ini->data[$anggota] = $nilai;
}
}
fungsi publik __destruct() {
$query = "PERBARUI " . $ini->tabel .
email = ?, negara = ? DIMANA id = ?";
$ini->dbh->query($query, $ini->nama, $ini->email,
$ini->negara, $ini->id);
}
}
$class = new Bertahan("Martin Jansen");
$kelas->nama = "John Doe";
$class->negara = "Amerika Serikat";
$kelas->email = " [email protected] ";
?>
Masalah pertama yang mungkin Anda temui adalah __construct(), metode konstruktor baru yang diperkenalkan di PHP 5. Pada zaman PHP 4, konstruktor selalu mencocokkan nama kelasnya. Ini tidak lagi terjadi di PHP 5. Anda tidak perlu tahu banyak tentang metode konstruktor, kecuali bahwa memanggilnya akan membuat turunan kelas; dan perhatikan bahwa parameter digunakan di sini - database dijalankan berdasarkan parameter ini. Konstruktor ini menugaskan hasil kueri ke atribut kelas $data.
Selanjutnya, program mendefinisikan dua metode khusus __get() dan __set(). Anda pasti sudah mengenalnya: __get() digunakan untuk membaca nilai atribut yang tidak ditentukan, dan __set() digunakan untuk mengubah nilai atribut yang tidak ditentukan.
Ini berarti bahwa setiap kali properti yang tidak ditentukan dibaca/ditulis dari kelas penyimpanan persisten, metode khusus ini bertanggung jawab untuk mengelola informasi dalam variabel array properti $data, daripada secara langsung mengubah properti kelas tersebut (ingat: Variabel $data berisi baris dari database!).
Metode terakhir dalam sebuah kelas adalah kebalikan dari __construct() - destruktor __destruct(). PHP memanggil destruktor selama "fase penghentian skrip", yang biasanya mendekati akhir eksekusi skrip PHP. Destruktor menulis informasi dari atribut $data kembali ke database. Inilah arti istilah sinkronisasi sebelumnya.
Anda mungkin telah memperhatikan bahwa kode di sini menggunakan paket lapisan abstraksi database PEAR. Sebenarnya tidak masalah. Berkomunikasi dengan database melalui metode lain juga bisa menggambarkan tema artikel ini.
Jika Anda perhatikan baik-baik, Anda akan menemukan bahwa deskripsi kelas penyimpanan persisten ini relatif sederhana. Contoh ini hanya melibatkan tabel database, dan tidak mempertimbangkan model data yang lebih kompleks, seperti penggunaan LEFT JOIN dan teknik operasi database kompleks lainnya. Namun, Anda tidak harus terikat dengan hal ini, dan dengan bantuan kelebihan properti, Anda dapat menggunakan model database ideal Anda sendiri. Hanya dengan sedikit kode, Anda dapat memanfaatkan fitur database kompleks di kelas penyimpanan persisten ini.
Ada juga masalah kecil - tidak ada mekanisme penanganan kesalahan yang diperkenalkan ketika kueri gagal di destruktor. Sifat destruktorlah yang membuat pesan kesalahan yang sesuai tidak dapat ditampilkan dalam kasus ini, karena pembuatan markup HTML sering kali berakhir sebelum PHP memanggil destruktor.
Untuk mengatasi masalah ini, Anda dapat mengganti nama __destruct() menjadi sesuatu seperti saveData() dan menjalankan metode ini secara manual di suatu tempat di skrip pemanggil. Ini tidak mengubah konsep penyimpanan persisten untuk kelas; ini hanya beberapa baris kode lagi. Alternatifnya, Anda dapat menggunakan fungsi error_log() di destruktor untuk mencatat pesan kesalahan ke file log kesalahan seluruh sistem.
Beginilah cara kerja kelebihan beban properti. Selanjutnya kita membahas metode Overloading.
4. Contoh kelebihan metode
1. Metode Pengambil/Penyetel Dinamis
Kode berikut mengimplementasikan metode pengambil/penyetel "dinamis" untuk mengontrol kelas dengan bantuan metode kelebihan beban. Mari kita analisa berdasarkan source code:
<?php
kelas DynamicGetterSetter {
pribadi $nama = "Martin Jansen";
pribadi $starbucksdrink = "Aduk Karamel Cappuccino";
fungsi __panggilan($metode, $argumen) {
$awalan = strtolower(substr($metode, 0, 3));
$properti = strtolower(substr($metode, 3));
if (kosong($awalan) || kosong($properti)) {
kembali;
}
if ($awalan == "dapatkan" && isset($ini->$properti)) {
kembalikan $ini->$properti;
}
if ($awalan == "set") {
$ini->$properti = $argumen[0];
}
}
}
$kelas = DynamicGetterSetter baru;
gema "Nama: " $kelas->getName() .
echo "Rasa Starbucks favorit: " $class->getStarbucksDrink() "nn";
$kelas->setName("John Doe");
$class->setStarbucksDrink("Kopi Klasik");
gema "Nama: " $kelas->getName() .
echo "Rasa Starbucks favorit: " $class->getStarbucksDrink() "nn";
?>
Jelas kedua atribut $name dan $starbucksdrink di sini bersifat private yang artinya atribut tersebut tidak dapat diakses dari luar kelas. Dalam pemrograman berorientasi objek, sangat umum untuk menerapkan metode pengambil/penyetel publik untuk mengakses atau mengubah nilai properti non-publik. Menerapkan hal ini membosankan dan memakan waktu serta tenaga.
Masalah ini dapat dengan mudah diselesaikan dengan bantuan metode kelebihan beban. Daripada menerapkan metode pengambil/penyetel untuk setiap properti, metode di atas hanya mengimplementasikan metode __call() umum. Ini berarti ketika metode pengambil/penyetel yang tidak terdefinisi seperti setName() atau getStarbucksdrink() dipanggil, PHP tidak akan menghasilkan kesalahan fatal dan dibatalkan, melainkan mengeksekusi (atau mendelegasikan ke) metode ajaib __call().
Ini adalah beberapa perkenalan singkat. Mari kita lakukan analisis mendalam tentang __call().
2. Analisis mendetail dari metode __call().
Parameter pertama dari __call() adalah metode asli dan belum ditentukan (seperti setName). Parameter kedua adalah array satu dimensi dengan indeks numerik, yang berisi semua metode asli .parameter. Memanggil metode yang tidak terdefinisi dengan dua parameter ("Martin" dan 42) akan menghasilkan array berikut:
$class->thisMethodDoesNotExist("Martin", 42);
/Panduan ke parameter kedua __call()
Himpunan
(
[0] =>Martin
[1] => 42
)
Di dalam metode __call(), jika metode asli dimulai dengan get atau set, beberapa perhitungan harus dilakukan untuk menentukan apakah kode tersebut memanggil metode pengambil/penyetel. Selain itu, metode ini akan menganalisis lebih lanjut komponen lain dari nama metode (kecuali tiga karakter pertama), karena bagian terakhir dari string mewakili nama atribut yang direferensikan oleh pengambil/penyetel.
Jika nama metode menunjukkan pengambil/penyetel, maka metode tersebut akan mengembalikan nilai properti terkait atau menetapkan nilai parameter pertama dari metode asli. Jika tidak, ia tidak melakukan apa pun dan terus menjalankan program seolah-olah tidak terjadi apa-apa.
3. Untuk mencapai tujuan
Intinya, sesuai dengan atribut apa pun, ada metode yang memungkinkan kode untuk secara dinamis memanggil metode pengambil/penyetel apa pun. Algoritma ini ada. Hal ini berguna ketika mengembangkan prototipe program dalam jangka pendek: daripada menghabiskan banyak waktu mengimplementasikan getter/setter, pengembang dapat fokus pada pemodelan API dan memastikan bahwa aplikasi tersebut benar secara fundamental. Memasukkan metode __call() ke dalam kelas abstrak bahkan memungkinkan Anda untuk menggunakan kembali kode dalam pengembangan proyek PHP di masa depan
4. Selain kekurangan,
ada kelebihan dan kekurangannya! Ada beberapa kelemahan pendekatan di atas: Proyek yang lebih besar mungkin menggunakan alat seperti phpDocumentor untuk melacak struktur API. Dengan metode dinamis yang diperkenalkan di atas, tentu saja semua metode pengambil/penyetel tidak akan muncul di dokumen yang dibuat secara otomatis, sehingga tidak memerlukan penjelasan lebih lanjut.
Kelemahan lainnya adalah kode di luar kelas dapat mengakses setiap properti pribadi di dalam kelas. Saat menggunakan metode pengambil/penyetel nyata, dimungkinkan untuk membedakan antara properti pribadi yang dapat diakses oleh kode eksternal dan properti pribadi "nyata" yang tidak terlihat di luar kelas - karena kami memiliki metode yang kelebihan beban, dan kami memiliki pengambil dan penyetel virtual Metode dapat digunakan.
5. Kesimpulan
Artikel ini menganalisis dengan cermat dua situasi kelebihan beban objek di PHP 5.0 melalui dua contoh. Saya sangat berharap metode dalam artikel ini dapat membantu Anda meningkatkan efisiensi pemrograman PHP! Pada saat yang sama, Anda juga harus melihat dengan jelas kekurangan metode ini.