1. Pendahuluan
Mengimplementasikan tipe objek wajib di PHP terkadang menjadi sangat penting. Jika hilang, baik karena kurangnya pengetahuan - berdasarkan asumsi pemrograman yang salah, atau hanya kemalasan - maka Anda akan melihat hasil yang tidak Anda harapkan dalam aplikasi web khusus Anda. Terutama ketika pemrograman di PHP 4, sangat mudah untuk menggunakan fungsi "is_a()" (walaupun ada metode lain) untuk memverifikasi jenis objek yang Anda kerjakan. Tentu saja, tipe objek yang dipaksakan juga dapat digunakan untuk memfilter objek input yang perlu diteruskan sebagai parameter ke kelas PHP lain dalam aplikasi yang sama.
Namun, PHP 4 tidak memperlihatkan beberapa kelemahan pada model objeknya - terkadang memerlukan penulisan kode tambahan untuk mengimplementasikan fitur tertentu yang ditemukan dalam bahasa berorientasi objek yang sudah matang. Fakta ini sudah lama diketahui komunitas PHP. Namun, dengan dirilisnya PHP 5, banyak fitur yang sangat berharga ini ditambahkan sebagai bagian dari model objek yang ditingkatkan. Mereka akan membantu mengimplementasikan pengembangan kode berbasis objek secara lebih dekat - memungkinkan Anda menggunakan karakteristik objek tertentu.
Dalam kasus di atas, perhatian khusus harus diberikan ketika berhubungan dengan pemaksaan jenis objek. Faktanya, PHP 5 memberi pengembang setidaknya dua cara untuk memeriksa tipe objek selama eksekusi aplikasi web - yaitu dengan operator "instanceof" dan fitur "type petunjuk". Sekarang beralih ke topik utama artikel ini, saya akan memperkenalkan penggunaan operator "instanceof" di PHP 5, Anda akan segera menemukan bahwa ini bisa sangat memudahkan untuk menentukan apakah objek yang Anda kerjakan termasuk dalam tipe tertentu.
Artikel ini akan membantu Anda memahami cara mengimplementasikan tipe objek wajib di PHP 5 melalui beberapa contoh berorientasi objek.
2. Apa yang Tidak Harus Anda Lakukan
Untuk menunjukkan bagaimana menerapkan pemaksaan tipe objek di PHP 5, saya akan menggunakan kelas widget (X)HTML, dan kelas pembuat halaman sederhana, dengan modifikasi sederhana agar sesuai dengan lingkungan pengembangan PHP 5.
Contoh pertama saya mencantumkan beberapa kelas widget (X)HTML yang berasal dari kelas dasar abstrak "HTMLElement", yang melewatkan pemeriksaan jenis objek masukannya. Silakan lihat kelas berikut terlebih dahulu:
//Definisikan kelas abstrak 'HTMLElement'
kelas abstrak HTMLElement{
dilindungi $atribut;
fungsi yang dilindungi __construct($attributes){
if(!is_array($atribut)){
throw new Exception('Jenis atribut tidak valid');
}
$ini->atribut=$atribut;
}
// Metode abstrak 'getHTML()' fungsi abstrak yang dilindungi getHTML();
}
//Tentukan kelas spesifik 'Div'-extends HTMLElement
kelas Div memperluas HTMLElement{
pribadi $output='<div ';
pribadi $data;
fungsi publik __konstruksi($atribut=array(),$data){
induk::__konstruksi($atribut);
$ini->data=$data;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
$ini->keluaran.=$ini->data.'</div>';
kembalikan $ini->keluaran;
}
}
//Definisikan kelas konkrit 'Header1' - memperluas HTMLElement
kelas Header1 memperluas HTMLElement{
pribadi $output='<h1 ';
pribadi $data;
fungsi publik __konstruksi($atribut=array(),$data){
induk::__konstruksi($atribut);
$ini->data=$data;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
$ini->keluaran.=$ini->data.'</h1>';
kembalikan $ini->keluaran;
}
}
//Definisikan kelas konkret 'Paragraf' - memperluas HTMLElement
kelas Paragraf memperluas HTMLElement{
pribadi $output='<p ';
pribadi $data;
fungsi publik __konstruksi($atribut=array(),$data){
induk::__konstruksi($atribut);
$ini->data=$data;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
$ini->keluaran.=$ini->data.'</p>';
kembalikan $ini->keluaran;
}
}
//Definisikan kelas konkret 'UnorderedList' - memperluas HTMLElement
kelas UnorderedList memperluas HTMLElement{
pribadi $output='<ul ';
pribadi $item=array();
fungsi publik __construct($attributes=array(), $items=array()){
induk::__konstruksi($atribut);
if(!is_array($item)){
throw new Exception('Parameter tidak valid untuk item daftar');
}
$ini->barang=$barang;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
foreach($ini->item sebagai $item){
$this->output.='<li>'.$item.'</li>';
}
$ini->keluaran.='</ul>';
kembalikan $ini->keluaran;
}
}
Seperti yang Anda lihat, kelas widget (X)HTML di atas sangat berguna untuk menghasilkan elemen tertentu di web, namun saya sengaja menulis kode untuk setiap kelas sehingga tidak dapat memvalidasi efektivitas parameter input. Seperti yang mungkin Anda bayangkan, parameter masukan diteruskan langsung ke konstruktor kelas dan ditetapkan sebagai properti. Timbul pertanyaan: apakah ada yang salah dengan melakukan hal ini? Ya, ada. Sekarang, saya akan mendefinisikan kelas pembuat halaman paling sederhana dan memberinya widget seperti ini sehingga Anda dapat melihat bagaimana masukan ke kelas ini dicampur dengan objek yang salah. Berikut adalah tanda tangan dari kelas pembuat halaman:
class PageGenerator{
pribadi $keluaran='';
pribadi $judul;
fungsi publik __construct($title='Halaman Default'){
$ini->judul=$judul;
}
fungsi publik doHeader(){
$ini->output='<html><kepala><judul>'.$ini-
>judul.'</judul></kepala><badan>';
}
fungsi publik addHTMLElement($htmlElement){
$ini->output.=$htmlElement->getHTML();
}
fungsi publik doFooter(){
$ini->keluaran.='</body></html>';
}
fungsi publik ambilHTML(){
kembalikan $ini->keluaran;
}
}
Sekarang, kita mulai membuat instance beberapa objek widget (X)HTML dan meneruskannya ke kelas generator yang sesuai, seperti yang ditunjukkan dalam contoh berikut:
try{
//Buat beberapa elemen HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
elemen ada di sini');
$div=Div baru(array('name'=>'div1','class'=>'divclass'),'Konten untuk elemen Div
pergi ke sini');
$par=Paragraf baru(array('name'=>'par1','class'=>'parclass'),'Isi untuk Paragraf
elemen ada di sini');
$ul=Daftar Tidak Terurut baru(array ('nama'=>'daftar1', 'kelas'=>'kelasdaftar'), array
('item1'=>'nilai1', 'item2'=>'nilai2', 'item3'=>'nilai3'));
//Membuat instance kelas pembuat halaman $pageGen=new Page Generator();
$pageGen->doHeader();
//Tambahkan objek 'HTMLElement' $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
//Menampilkan halaman web echo $pageGen->fetchHTML();
}
tangkapan(Pengecualian $e){
gema $e->getMessage();
KELUAR();
}
Setelah menjalankan kode PHP di atas, hasil yang Anda dapatkan adalah halaman web sederhana - berisi beberapa objek (X)HTML yang dibuat sebelumnya. Dalam hal ini, mudah untuk memahami apa yang akan terjadi jika karena alasan tertentu kelas pembuat halaman menerima objek yang salah dan memanggil metode "addHTML()" miliknya. Di sini, saya telah mengerjakan ulang kondisi konflik - dengan menggunakan objek widget HTML (X) yang tidak ada. Silakan lihat kembali kode berikut:
coba{
//Buat beberapa elemen HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
elemen ada di sini');
$div=Div baru(array('name'=>'div1','class'=>'divclass'),'Konten untuk elemen Div
pergi ke sini');
$par=Paragraf baru(array('name'=>'par1','class'=>'parclass'),'Isi untuk Paragraf
elemen ada di sini');
$ul=Daftar Tidak Terurut baru(array ('nama'=>'daftar1', 'kelas'=>'kelasdaftar'), array
('item1'=>'nilai1', 'item2'=>'nilai2', 'item3'=>'nilai3'));
//Membuat instance kelas pembuat halaman $pageGen=new Page Generator();
$pageGen->doHeader();
//Tambahkan objek 'HTMLElement' $pageGen->addHTMLElement($fakeobj) //Lewati objek yang tidak ada ke metode ini $pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// Menampilkan halaman echo $pageGen->fetchHTML();
}
tangkapan(Pengecualian $e){
gema $e->getMessage();
KELUAR();
}
Dalam hal ini, seperti yang ditunjukkan pada baris berikut:
$pageGen->addHTMLElement($fakeobj)//Pass objek yang tidak ada ke metode ini
Objek widget HTML yang tidak ada (X) diteruskan ke kelas pembuat halaman, ini akan mengakibatkan kesalahan fatal:
Kesalahan fatal: Panggilan ke fungsi anggota pada non-objek di
Bagaimana dengan
jalur/ke/file
?Ini adalah penalti langsung karena tidak memeriksa jenis objek yang diteruskan ke kelas generator! Jadi pastikan untuk mengingat hal ini saat menulis skrip Anda. Untungnya, ada solusi sederhana untuk masalah ini, dan di sinilah kekuatan operator "instanceof" berperan. Jika Anda ingin melihat bagaimana operator ini digunakan, baca terus.
3. Gunakan operator "instanceof".
Seperti yang Anda lihat, penggunaan operator "instanceof" sangat sederhana. Ia menggunakan dua parameter untuk menyelesaikan fungsinya. Parameter pertama adalah objek yang ingin Anda periksa, dan parameter kedua adalah nama kelas (sebenarnya nama antarmuka) yang digunakan untuk menentukan apakah objek tersebut merupakan turunan dari kelas yang bersangkutan. Tentu saja, saya sengaja menggunakan terminologi di atas agar Anda dapat melihat betapa intuitifnya operator ini dalam menggunakannya. Sintaks dasarnya adalah sebagai berikut:
if (nama kelas instance objek){
//Lakukan sesuatu yang bermanfaat
}
Sekarang setelah Anda memahami bagaimana operator ini digunakan di PHP 5, mari kita tentukan kelas pembuat halaman web yang sesuai untuk memverifikasi jenis objek yang diteruskan ke metode "addHTMLElement()" miliknya. Berikut adalah tanda tangan baru dari kelas ini, yang saya sebutkan sebelumnya menggunakan operator "instanceof":
class PageGenerator{
pribadi $keluaran='';
pribadi $judul;
fungsi publik __construct($title='Halaman Default'){
$ini->judul=$judul;
}
fungsi publik doHeader(){
$this->output='<html><head><title>'.$this->title.'</title></head><body>';
}
fungsi publik addHTMLElement($htmlElement){
if(!$htmlElemen instance dari HTMLElement){
throw new Exception('Elemen HTML tidak valid (X)');
}
$ini->output.=$htmlElement->getHTML();
}
fungsi publik doFooter(){
$ini->keluaran.='</body></html>';
}
fungsi publik ambilHTML(){
kembalikan $ini->keluaran;
}
}
Perhatikan, pada kelas di atas, bagaimana operator "instanceof" disertakan dalam metode "addHTMLElement()" untuk memastikan bahwa semua objek yang diteruskan adalah turunan dari kelas "HTMLElement" yang ditentukan sebelumnya. Sekarang, dimungkinkan untuk merekonstruksi halaman web yang Anda lihat sebelumnya, dalam hal ini pastikan bahwa semua objek masukan yang diteruskan ke kelas pembuat halaman web adalah objek widget HTML (X) asli. Berikut adalah contoh yang sesuai:
coba{
//Buat beberapa elemen HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Konten untuk elemen H1 ada di sini');
$div=new Div(array('name'=>'div1', 'class'=>'divclass'), 'Konten untuk elemen Div ada di sini');
$par=Paragraf baru(array('name'=>'par1','class'=>'parclass'),'Isi untuk elemen Paragraf ada di sini');
$teststr='Ini bukan elemen HTML';
//Membuat instance kelas pembuat halaman $pageGen=new Page Generator();
$pageGen->doHeader();
//Tambahkan objek 'HTMLElement' $pageGen->addHTMLElement($teststr) //Masukkan string sederhana ke metode ini $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->doFooter();
//Menampilkan halaman web echo $pageGen->fetchHTML();
}
tangkapan(Pengecualian $e){
gema $e->getMessage();
KELUAR();
}
Seperti yang Anda lihat pada contoh di atas, saya meneruskan string pengujian sederhana (bukan objek "HTMLElement") ke dalam kelas pembuat halaman, yang akan memunculkan Exception - ditangkap oleh blok "catch" tertentu, seperti yang ditunjukkan di bawah ini:
Elemen HTML (X)Tidak Valid
Saat ini, untuk menentukan validitas objek input, saya menggunakan operator "instanceof", sehingga halaman web di atas dapat ditampilkan. Saya harap Anda benar-benar menghargai pentingnya memfilter input ke metode kelas Anda untuk menghindari kesalahan yang tidak relevan dengan menggunakan operator ini.
Setelah menunjukkan implementasi yang benar dari operator "instanceof" di dalam kelas generator halaman web, masih ada lagi yang harus dilakukan serupa dengan apa yang saya tulis untuk PHP 4 di artikel sebelumnya. (X). Untuk kelas widget HTML, saya ingin menyertakan operator ini sebagai bagian dari metode "getHTML()" mereka, sehingga memungkinkan pembuatan halaman web yang menghasilkan elemen HTML bersarang (X). Mari kita bahas bagaimana hal ini dilakukan.
4. Perluas penggunaan operator "instanceof": Widget HTML bersarang (X)
bagus. Anda telah melihat bahwa operator "instanceof" bekerja dengan baik dalam pemeriksaan tipe pada objek input yang langsung dimasukkan ke dalam fungsionalitas pembuat halaman. Sekarang, saya akan melangkah lebih jauh dan menambahkan pemeriksaan rutin ke konstruktor dan metode "getHTML()" dari kelas widget (X)HTML sehingga mereka dapat menerima widget lain sebagai parameter masukan. Silakan periksa peningkatan di bawah ini.
kelas Div memperluas HTMLElement{
pribadi $output='<div ';
pribadi $data;
fungsi publik __konstruksi($atribut=array(),$data){
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Jenis parameter tidak valid');
}
induk::__konstruksi($atribut);
$ini->data=$data;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
$this->output.=($this->data instance dari HTMLElement)?
$ini->data->getHTML():$ini->data;
$ini->keluaran.='</div>';
kembalikan $ini->keluaran;
}
}
kelas Header1 memperluas HTMLElement{
pribadi $output='<h1 ';
pribadi $data;
fungsi publik __konstruksi($atribut=array(),$data){
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Jenis parameter tidak valid');
}
induk::__konstruksi($atribut);
$ini->data=$data;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
$this->output.=($this->data instance dari HTMLElement)?
$ini->data->getHTML():$ini->data;
$ini->keluaran.='</h1>';
kembalikan $ini->keluaran;
}
}
kelas Paragraf memperluas HTMLElement{
pribadi $output='<p ';
pribadi $data;
fungsi publik __konstruksi($atribut=array(),$data){
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Jenis parameter tidak valid');
}
induk::__konstruksi($atribut);
$ini->data=$data;
}
//Implementasi spesifik dari fungsi publik metode 'getHTML()' getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
$this->output.=($this->data instance dari HTMLElement)?
$ini->data->getHTML():$ini->data;
$ini->keluaran.='</p>';
kembalikan $ini->keluaran;
}
}
kelas UnorderedList memperluas HTMLElement{
pribadi $output='<ul ';
pribadi $item=array();
fungsi publik __construct($attributes=array(), $items=array()){
induk::__konstruksi($atribut);
if(!is_array($item)){
throw new Exception('Parameter tidak valid untuk item daftar');
}
$ini->barang=$barang;
}
//Implementasi spesifik dari metode 'getHTML()'
fungsi publik getHTML(){
foreach($ini->atribut sebagai $atribut=>$nilai){
$ini->output.=$attribute.'="'.$value.'" ';
}
$ini->keluaran=substr_replace($ini->keluaran,'>',-1);
foreach($ini->item sebagai $item){
$ini->output.=($item instanceof
HTMLElement)?'<li>'.$item->getHTML().'</li>':'<li>'.$item.'</li>';
}
$ini->keluaran.='</ul>';
kembalikan $ini->keluaran;
}
}
Seperti yang ditunjukkan pada kelas di atas, untuk memungkinkan elemen HTML bersarang (X) diimplementasikan saat membuat halaman web terkait, saya memfaktorkan ulang konstruktornya dan metode "getHTML()" masing-masing. Perhatikan bahwa saya menyertakan blok kondisional berikut di konstruktor setiap kelas:
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Jenis parameter tidak valid');
}
Pada titik ini, apa yang sebenarnya saya lakukan adalah memastikan bahwa hanya data string dan objek bertipe "HTMLElement" yang diperbolehkan sebagai parameter input untuk setiap kelas. Jika tidak, pengecualian akan dilempar oleh metode masing-masing dan dapat menyebabkan aplikasi menghentikan eksekusi. Nah, begitulah proses pengecekan data masukan. Sekarang, mari kita lihat tanda tangan baru dari metode "getHTML()", yang juga menggunakan operator "instanceof":
$this->output.=($this->data instanceof HTMLElement)?$this->data-
>getHTML():$this->data;
Seperti yang Anda lihat, dalam kasus ini, operator ini sangat berguna untuk memanfaatkan fitur polimorfik kelas widget (X)HTML. Jika atribut $data juga merupakan widget, maka metode "getHTML()"-nya akan dipanggil dengan benar, yang akan menyebabkan elemen web bertumpuk ditampilkan. Di sisi lain, jika itu hanya sebuah string, maka itu ditambahkan langsung ke semua output dari kelas saat ini.
Pada titik ini, Anda mungkin telah memahami penggunaan operator "instanceof" di PHP 5 untuk memastikan bahwa objek tertentu termasuk dalam tipe tertentu. Seperti yang Anda lihat di artikel ini, memaksa tipe objek di PHP 5 sebenarnya adalah tugas yang cukup mudah. Untuk saat ini, sebaiknya Anda mengembangkan contoh penggunaan metode ini untuk memfilter objek dalam aplikasi PHP Anda untuk memperdalam pemahaman Anda.
5. Ringkasan
Pada artikel ini, Anda mempelajari cara menggunakan operator "instanceof" di PHP 5 untuk memeriksa tipe objek input Anda, namun metode yang saya tunjukkan bukan satu-satunya. Di artikel selanjutnya, saya akan menjelaskan kepada Anda cara mengimplementasikan fitur "type petunjuk" yang bagus di PHP 5, yang merupakan cara lain untuk menerapkan pengetikan objek.
Penulis: Zhu Xianzhong Sumber Penyusun: Pengembangan Tianji