متد های جادویی (Magic Methods)

Constructor:یکی از متد های جادویی construct__ هست.در زمان ساخت آبجکت از یک کلاس , این متد اجرا میشه.class BaseClass { public function __construct() { echo &quotIn BaseClass constructor&quot } } // In BaseClass constructor $obj = new BaseClass(); // __construct() will be runزمان new عبارت "In BaseClass constructor" چاپ میشه.حالا کلاسی دیگه میسازیم که از BaseClass مشتق شده باشه و متد construct رو در خودش داره:class SubClass extends BaseClass { function __construct() { parent::__construct(); echo &quotIn SubClass constructor&quot } } // In BaseClass constructor // In SubClass constructor $obj = new SubClass();* با دستور parent میتونیم متد های کلاس والد رو فراخوانی کنیم:parent::MethodNameدر حالت بعدی کلاسی مشتق شده از BaseClass داریم ولی این کلاس متد construct نداره:class OtherSubClass extends BaseClass { // inherits BaseClass's constructor } // In BaseClass constructor $obj = new OtherSubClass();این کلاس , چون متد construct نداره , از والد خودش (BaseClass) این متدو به ارث میبره.نوع دیگری برای پیاده سازی constructor , ساخت یک متد همنام با کلاس:class Bar { public function Bar() { echo &quotIn Bar constructor&quot } } // In Bar constructor $obj = new Bar();Destructor :متد جادویی دیگری که در php تعریف شده destruct__ هست.این متد در زمان از بین رفتن آبجکت یا به پایان رسیدن اسکریپت , اجرا میشود.class Example { public function __construct() { print &quotIn constructor<br>&quot $this->name = &quotExample&quot } public function __destruct() { echo &quotDestroying &quot . $this->name; } } $obj = new Example();نتیجه ای که میبینیم:In constructor Destroying Exampleشاید بنظرتون برسه دو متد , با ساخت آبجکت , همزمان اجرا شدن ولی دلیل اجرای destructor به پایان رسیدن اسکریپت هست.واسه نشون دادن این مسئله , یک مثال دیگه میزنم:class Example { public function __construct() { print &quotIn constructor<br>&quot $this->name = &quotExample&quot } public function __destruct() { echo &quotDestroying &quot . $this->name; } } $obj = new Example(); echo 'Numbers: '; for($i = 1; $i <= 10; $i++) { echo $i . ' '; } echo '<br>';نتیجه ی حاصل از اسکریپت بالا:In constructor Numbers: 1 2 3 4 5 6 7 8 9 10 Destroying Exampleمورد دیگه ای که در اول متن گفتم , اجرای destructor در زمان از بین رفتن آبجکت:class Example { public function __construct() { print &quotIn constructor<br>&quot $this->name = &quotExample&quot } function __destruct() { echo &quotDestroying &quot . $this->name; } } $obj = new Example(); echo 'Numbers:<br>'; unset($obj); // __destruct() will be run echo '<br>'; for($i = 1; $i <= 10; $i++) { echo $i . ' '; } echo '<br>';نتیجه ی اسکریپت:In constructor Numbers: Destroying Example 1 2 3 4 5 6 7 8 9 10همونطور که میبینید , با استفاده از تابع unset , آبجکت کلاس رو حذف کردیم که باعث فراخوانی متد destructor شد.Getter :متد get__ در زمان خواندن یک فیلد , اجرا میشود.class Example { private $name; private $family; public function __construct() { $this->name = 'Mohsen'; $this->family = 'Movahed'; } } $obj = new Example(); echo $obj->name . ' ' . $obj->family; // errorنتیجه با اررور مواجه میشه.متن اررور:Error: Cannot access private property Example::$nameعلت: فیلد های private , بیرون از کلاس قابل دسترسی نیستن.حالا با توجه به تعریفی که از getter داشتیم , زمان صدا زدن فیلد (echo $obj->name) , متد get__ (در صورتی که تعریف شده باشه) , اجرا میشه:class Example { private $name; // field 1 private $family; // field 2 public function __construct() { $this->name = 'Mohsen'; $this->family = 'Movahed'; } public function __get($field) { return $this->$field; } } $obj = new Example(); echo $obj->name . ' ' . $obj->family; // Mohsen Movahed //****************OR******************// $obj = new Example(); $name = $obj->name; // __get() will be run $family = $obj->family; // __get() will be run echo $name . ' ' . $family; // Mohsen Movahedحالا با وجود متد get , فیلدها از داخل خود کلاس مورد دستیابی قرار میگیرن و در چاپ نام و فامیل , این متد دو بار اجرا میشود.***************************************************Setter :متد set__ در زمان مقدار دهی فیلدها اجرا خواهد شد.دو آرگومان داره:نام فیلدمقدارclass Example { private $name; // field 1 private $family; // field 2 public function __get($field) { return $this->$field; } public function __set($field, $value) { $this->$field = $value; } } $obj = new Example(); $obj->name = 'Mohsen'; // __set() will be run $obj->family = 'Movahed'; // __set() will be run echo $obj->name . ' ' . $obj->family; // Mohsen Movahedپیاده سازی getter و setter به روشی دیگر: (برای مثال)class Example { private $fields; public function __construct() { $this->fields = array( 'name' => null, 'family' => null, 'age' => null, ); } public function __get($key) { if(array_key_exists($key, $this->fields)) { return $this->fields[$key]; } return false; } public function __set($key, $value) { if(array_key_exists($key, $this->fields)) { $this->fields[$key] = $value; } } } $obj = new Example(); $obj->name = 'Mohsen'; $obj->family = 'Movahed'; $obj->age = 23; $obj->email = 'l3iidak@gmail.com'; echo $obj->name . ' ' . $obj->family . ' ' . $obj->age . ' ' . $obj->email; // Mohsen Movahed 23email جزو ایندکس ها نیست , بنابراین مقدار دهی نمیشود.* به شکل های مختلف و اعتبار سنجی ها متفاوت میتونید این دو متدو پیاده سازی کنید.Call :وقتی توسط یک آبجکت , متدی رو فراخوانی کنیم که در کلاس مورد نظر وجود نداشته باشد , متد call__ اجرا میشود.دو آرگومان دارد:نام متدآرگومان های ارسالیclass MethodTest { public function __call($method, $arguments) { // Note: value of $mthod is case sensitive. echo &quotCalling object method <strong>'$method'</strong> with arguments:<br>&quot echo '<pre>'. print_r($arguments, true) .'</pre>'; } public function display() { echo 'Display Method' . '<br>'; } } $obj = new MethodTest(); $obj->display(); // Display Method $obj->runTest(1, 2, 3, 4);متدهایی که در کلاس وجود دارند , اگر فراخوانی شوند خود متد ها اجرا می شوند , بنابراین متد display اجرا میشود.اما چون متد runTest در کلاس وجود ندارد , متد Call__ اجرا میشود. (نام متد: runTest - آرگومان ها : 1 , 2 , 3 , 4)نتیجه ی کد بالا:Display Method Calling object method 'runTest' with arguments: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )callStatic :متد callStatic__ هم مانند متد call__ عمل میکند با این تفاوت که برای متد های استاتیک هست.class MethodTest { public static function __callStatic($method, $arguments) { // Note: value of $method is case sensitive. echo &quotCalling static method <strong>'$method'</strong> with arguments: &quot . implode(', ', $arguments) . PHP_EOL; } } MethodTest::runTest('in static context');نتیجه:Calling static method 'runTest' with arguments: in static contextادامه دارد...نویسنده: محسن موحد