PHP menyediakan sejumlah metode 'ajaib' yang memungkinkan anda untuk melakukan beberapa trik yang cukup rapi dalam pemrograman berorientasi objek. Metode-metode ini, yang diidentifikasi oleh dua prefiks garis bawah (__), berfungsi sebagai pencegat yang secara otomatis dipanggil ketika kondisi tertentu terpenuhi. Metode sulap menyediakan beberapa fungsi yang sangat berguna, dan tutorial ini akan mendemonstrasikan penggunaan setiap metode. Show
Sebelum Kita MulaiUntuk sepenuhnya memahami metode sulap, ada gunanya melihat mereka beraksi. Jadi mari kita mulai dengan satu set dasar dari kelas yang sangat sederhana. Di sini kita mendefinisikan dua kelas: Perangkat dan Baterai. <?php class Device { public $name; // the name of the device public $battery; // holds a Battery object public $data = array(); // stores misc. data in an array public $connection; // holds some connection resource protected function connect() { // connect to some external network $this->connection = 'resource'; echo $this->name . ' connected' . PHP_EOL; } protected function disconnect() { // safely disconnect from network $this->connection = null; echo $this->name . ' disconnected' . PHP_EOL; } } class Battery { private $charge = 0; public function setCharge($charge) { $charge = (int)$charge; if($charge < 0) { $charge = 0; } elseif($charge > 100) { $charge = 100; } $this->charge = $charge; } } ?>
Objek perangkat akan menyimpan nama, objek Battery, array data, dan pegangan ke beberapa sumber eksternal. Mereka juga memiliki metode untuk menghubungkan dan memutuskan sumber daya eksternal. Objek baterai cukup menyimpan muatan dalam properti pribadi dan memiliki metode untuk mengatur biaya. Tutorial ini mengasumsikan anda memiliki pemahaman dasar tentang pemrograman berorientasi objek. Jika kata-kata seperti "metode" dan "properti" terdengar asing bagi anda, anda mungkin ingin membaca tentang itu terlebih dahulu. Kelas-kelas ini sangat tidak berguna, tetapi mereka menjadi contoh yang baik untuk masing-masing metode sihir. Jadi sekarang kita telah membuat kelas sederhana, kita bisa mencoba metode sulap. Pembangun & DestruktorKonstruktor dan destruktor disebut ketika suatu objek dibuat dan dihancurkan, masing-masing. Suatu objek "dihancurkan" ketika tidak ada referensi lagi untuk itu, baik karena variabel yang memegangnya tidak disetel / dialihkan atau skrip berakhir eksekusi. __construct()Metode class Device { //... public function __construct(Battery $battery, $name) { // $battery can only be a valid Battery object $this->battery = $battery; $this->name = $name; // connect to the network $this->connect(); } //... }
Di sini kami telah mendeklarasikan konstruktor yang menerima dua argumen, Baterai dan nama. Konstruktor menetapkan masing-masing properti yang dibutuhkan objek untuk berfungsi dan menjalankan metode Tip: Mendeklarasikan metode konstruktor 'pribadi' mencegah kode eksternal secara langsung membuat objek. Ini berguna untuk membuat kelas tunggal yang membatasi jumlah objek yang bisa ada. Dengan konstruktor di atas di tempat, di sini adalah bagaimana anda membuat Perangkat yang disebut 'iMagic': $device = new Device(new Battery(), 'iMagic'); // iMagic connected echo $device->name; // iMagic Seperti yang Anda lihat, argumen yang dilewatkan ke kelas benar-benar diteruskan ke metode
konstruktor. Anda juga dapat mengatakan bahwa metode penghubung dipanggil dan properti Katakanlah kita lupa untuk memberikan nama. Inilah yang terjadi: $device = new Device(new Battery()); // Result: PHP Warning: Missing argument 2 for Device::__construct() __destruct()Seperti namanya, metode __destruct () dipanggil ketika objek dihancurkan. Ia tidak menerima argumen dan biasanya digunakan untuk melakukan operasi pembersihan seperti menutup koneksi database. Dalam kasus kami, kami akan menggunakannya untuk memutuskan sambungan dari jaringan. class Device { //... public function __destruct() { // disconnect from the network $this->disconnect(); echo $this->name . ' was destroyed' . PHP_EOL; } //... } Dengan destruktor di atas di tempat, inilah yang terjadi ketika objek Perangkat dihancurkan: $device = new Device(new Battery(), 'iMagic'); // iMagic connected unset($device); // iMagic disconnected // iMagic was destroyed Di sini, kami telah menghancurkan objek menggunakan Properti OverloadingCatatan: Versi PHP dari "overloading" tidak sama dengan kebanyakan bahasa lain, meskipun hasil yang sama dapat dicapai. Set metode sulap berikutnya adalah tentang berurusan dengan akses properti, mendefinisikan apa yang terjadi ketika anda mencoba mengakses properti yang tidak ada (atau tidak dapat diakses). Mereka dapat digunakan untuk membuat properti pseudo. Ini disebut overloading di PHP. __get()Metode class Device { //... public function __get($name) { // check if the named key exists in our array if(array_key_exists($name, $this->data)) { // then return the value from the array return $this->data[$name]; } return null; } //... } Penggunaan populer dari metode class Battery { private $charge = 0; public function __get($name) { if(isset($this->$name)) { return $this->$name; } return null; } //... } Dalam contoh ini, perhatikan penggunaan variabel variabels untuk mengakses properti secara dinamis. Dengan asumsi nilai 'pengguna' untuk __set()Metode class Device { //... public function __set($name, $value) { // use the property name as the array key $this->data[$name] = $value; } //... } __isset()Metode class Device { //... public function __isset($name) { // you could also use isset() here return array_key_exists($name, $this->data); } //... } __unset()Metode class Device { //... public function __unset($name) { // forward the unset() to our array element unset($this->data[$name]); } //... } Property Overloading in ActionBerikut adalah semua metode ajaib terkait properti yang telah kami nyatakan: class Device { //... public $data = array(); // stores misc. data in an array //... public function __get($name) { // check if the named key exists in our array if(array_key_exists($name, $this->data)) { // then return the value from the array return $this->data[$name]; } return null; } public function __set($name, $value) { // use the property name as the array key $this->data[$name] = $value; } public function __isset($name) { // you could also use isset() here return array_key_exists($name, $this->data); } public function __unset($name) { // forward the unset() to our array element unset($this->data[$name]); } //... } Dengan metode sulap di atas, inilah yang terjadi ketika kita mencoba mengakses properti yang disebut nama. Ingat bahwa sebenarnya tidak ada properti $device->user = 'Steve'; echo $device->user; // Steve Kami telah menetapkan dan berhasil mengambil nilai dari properti yang tidak ada. Nah di mana itu disimpan? print_r($device->data); /* Array ( [user] => Steve ) */ Seperti yang anda lihat, properti var_dump(isset($device->user)); // bool(true) Di atas adalah hasil pemanggilan unset($device->user); var_dump(isset($device->user)); // bool(false) Di atas adalah hasil dari unsetting the fake property. Hanya untuk memastikan, inilah larik data kosong kami: print_r($device->data); /* Array ( ) */ Mewakili Objek Sebagai TeksTerkadang anda mungkin ingin mengonversi objek ke representasi string. Jika anda mencoba mencetak objek, kami akan mendapatkan kesalahan, seperti yang di bawah ini: $device = new Device(new Battery(), 'iMagic'); echo $device; // Result : PHP Catchable fatal error: Object of class Device could not be converted to string __toSrting()Metode class Device { ... public function __toString() { // are we connected? $connected = (isset($this->connection)) ? 'connected' : 'disconnected'; // how much data do we have? $count = count($this->data); // put it all together return $this->name . ' is ' . $connected . ' with ' . $count . ' items in memory' . PHP_EOL; } ... } Dengan metode di atas didefinisikan, inilah yang terjadi ketika kami mencoba mencetak objek Perangkat: $device = new Device(new Battery(), 'iMagic'); echo $device; // iMagic is connected with 0 items in memory Objek Perangkat sekarang diwakili oleh ringkasan singkat yang berisi nama, status, dan jumlah item yang disimpan. __set_state() (PHP 5.1)Metode statis class Battery { //... public static function __set_state(array $array) { $obj = new self(); $obj->setCharge($array['charge']); return $obj; } //... } Metode kami cukup membuat instance kelas induknya dan menetapkan untuk mengisi ke nilai dalam larik yang diteruskan. Dengan metode di atas didefinisikan, inilah yang terjadi ketika kita menggunakan $device = new Device(new Battery(), 'iMagic'); var_export($device->battery); /* Battery::__set_state(array( 'charge' => 0, )) */ eval('$battery = ' . var_export($device->battery, true) . ';'); var_dump($battery); /* object(Battery)#3 (1) { ["charge:private"]=> int(0) } */ Komentar pertama menunjukkan apa yang sebenarnya terjadi, yaitu bahwa Kloning obyekObjek, secara default, dilewatkan oleh referensi. Jadi menugaskan variabel lain ke objek tidak akan benar-benar menyalin objek, itu hanya akan membuat referensi baru ke objek yang sama. Untuk benar-benar menyalin objek, kita harus menggunakan kata kunci Kebijakan 'pass by reference' ini juga berlaku untuk objek dalam objek. Bahkan jika kita mengkloning suatu objek, setiap objek anak yang ada di dalamnya tidak akan dikloning. Jadi kita akan berakhir dengan dua objek yang berbagi objek anak yang sama. Berikut ini contoh yang menggambarkan bahwa: $device = new Device(new Battery(), 'iMagic'); $device2 = clone $device; $device->battery->setCharge(65); echo $device2->battery->charge; // 65 Di sini, kami telah mengkloning objek Perangkat. Ingat bahwa semua objek Perangkat berisi objek Baterai. Untuk mendemonstrasikan bahwa kedua klon Perangkat berbagi Baterai yang sama, perubahan yang kami lakukan pada Baterai perangkat ini tercermin dalam baterai $device2. __clone()Metode class Device { ... public function __clone() { // copy our Battery object $this->battery = clone $this->battery; } ... } Dengan metode ini dinyatakan, kita sekarang dapat memastikan Perangkat yang dikloning masing-masing memiliki Baterai sendiri. $device = new Device(new Battery(), 'iMagic'); $device2 = clone $device; $device->battery->setCharge(65); echo $device2->battery->charge; // 0 Perubahan pada satu Baterai Perangkat tidak mempengaruhi yang lain. Serialisasi ObjekSerialisasi adalah proses yang mengubah data apa pun menjadi format string. Ini dapat digunakan untuk menyimpan seluruh objek ke dalam file atau basis data. Saat anda melakukan unserialize data yang tersimpan, anda akan memiliki objek aslinya persis seperti sebelumnya. Satu masalah dengan serialisasi, adalah bahwa tidak semuanya bisa diserialkan, seperti koneksi database. Untungnya ada beberapa metode sulap yang memungkinkan kita menangani masalah ini. __sleep()Metode Tip: Hindari melakukan sesuatu yang merusak dalam Dalam contoh Perangkat kami, properti koneksi mewakili sumber daya eksternal yang tidak dapat diserialkan. Jadi metode class Device { public $name; // the name of the device public $battery; // holds a Battery object public $data = array(); // stores misc. data in an array public $connection; // holds some connection resource //... public function __sleep() { // list the properties to save return array('name', 'battery', 'data'); } //... }
__wakeup()Metode Dalam contoh Perangkat kami, kami hanya perlu membangun kembali koneksi kami dengan memanggil metode class Device { //... public function __wakeup() { // reconnect to the network $this->connect(); } //... } Metode OverloadingKedua metode terakhir ini untuk menangani metode. Ini adalah konsep yang sama dengan metode overload properti ( __call()
Dalam contoh, perhatikan penggunaan fungsi Dalam contoh kami, kami akan meneruskan pemanggilan metode ke properti class Device { //... public function __call($name, $arguments) { // make sure our child object has this method if(method_exists($this->connection, $name)) { // forward the call to our child object return call_user_func_array(array($this->connection, $name), $arguments); } return null; } //... } Metode di atas akan dipanggil jika kita mencoba memanggil metode $device = new Device(new Battery(), 'iMagic'); $device->iDontExist(); // __call() forwards this to $device->connection->iDontExist() __callStatic() (PHP 5.3)
Satu-satunya perbedaan dalam contoh kami adalah bahwa kami menyatakan metode sebagai class Device { //... public static function __callStatic($name, $arguments) { // make sure our class has this method if(method_exists('Connection', $name)) { // forward the static call to our class return call_user_func_array(array('Connection', $name), $arguments); } return null; } //... } Metode di atas akan dipanggil jika kita mencoba memanggil metode statis Device::iDontExist(); // __callStatic() forwards this to Connection::iDontExist() Menggunakan Objek sebagai FungsiTerkadang anda mungkin ingin menggunakan objek sebagai fungsi. Mampu menggunakan objek sebagai fungsi memungkinkan anda untuk meneruskan fungsi di sekitar sebagai argumen seperti yang anda bisa dalam bahasa lain. __invoke() (PHP 5.3)
class Device { //... public function __invoke($data) { echo $data; } //... } Dengan definisi di atas, inilah yang terjadi ketika kita menggunakan Perangkat sebagai fungsi: $device = new Device(new Battery(), 'iMagic'); $device('test'); // equiv to $device->__invoke('test') // Outputs: test Bonus: __autoload()Ini bukan metode sulap, tetapi masih sangat berguna. Fungsi Fungsi ini menerima satu argumen: nama kelas yang direferensikan. Katakanlah anda memiliki setiap kelas dalam sebuah file bernama 'classname.class.php' di direktori 'inc'. Berikut adalah tampilan otomatis anda: function __autoload($class_name) { $class_name = strtolower($class_name); include_once './inc/' . $class_name . '.class.php'; } KesimpulanMetode-metode ajaib sangat berguna dan menyediakan alat yang kuat untuk mengembangkan kerangka kerja aplikasi yang fleksibel. Mereka membawa objek PHP lebih dekat ke objek lain yang berorientasi bahasa dengan memungkinkan anda untuk mereproduksi beberapa fitur mereka yang lebih bermanfaat. Anda dapat membaca halaman manual PHP tentang metode sulap di sini. Saya harap tutorial ini membantu dan menjelaskan konsepnya dengan jelas. Jika anda memiliki pertanyaan, jangan ragu untuk bertanya di komentar. Terima kasih sudah membaca. |