محسن موحد (آموزش برنامه نویسی)
محسن موحد (آموزش برنامه نویسی)
خواندن ۵ دقیقه·۳ سال پیش

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


یکی از متد های جادویی 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();




متد جادویی دیگری که در 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 شد.




متد 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 , فیلدها از داخل خود کلاس مورد دستیابی قرار میگیرن و در چاپ نام و فامیل ,  این متد دو بار اجرا میشود.

***************************************************

متد set__ در زمان مقدار دهی فیلدها اجرا خواهد شد.
دو آرگومان داره:

  1. نام فیلد
  2. مقدار
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 23

email جزو ایندکس ها نیست , بنابراین مقدار دهی نمیشود.
* به شکل های مختلف و اعتبار سنجی ها متفاوت میتونید این دو متدو پیاده سازی کنید.




وقتی توسط یک آبجکت , متدی رو فراخوانی کنیم که در کلاس مورد نظر وجود نداشته باشد , متد call__ اجرا میشود.

دو آرگومان دارد:

  1. نام متد
  2. آرگومان های ارسالی
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__ هم مانند متد 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



ادامه دارد...

نویسنده: محسن موحد

phpmagic methodconstructordestructorبرنامه نویسی
برنامه نویس متخصص PHP، Mysql، Javascript، HTML، CSS، Node.js، Android، Laravel، Yii2 - مدیر پشتیبانی فنی و سرپرست منتورها در شرکت 7learn.com
شاید از این پست‌ها خوشتان بیاید