متد های جادویی (Magic Methods)
یکی از متد های جادویی construct__ هست.
در زمان ساخت آبجکت از یک کلاس , این متد اجرا میشه.
class BaseClass
{
public function __construct()
{
echo "In BaseClass constructor";
}
}
// 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 "In SubClass constructor"; } } // 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 "In Bar constructor"; } } // In Bar constructor $obj = new Bar();
متد جادویی دیگری که در php تعریف شده destruct__ هست.
این متد در زمان از بین رفتن آبجکت یا به پایان رسیدن اسکریپت , اجرا میشود.
class Example { public function __construct() { print "In constructor<br>"; $this->name = "Example"; } public function __destruct() { echo "Destroying " . $this->name; } } $obj = new Example();
نتیجه ای که میبینیم:
In constructor Destroying Example
شاید بنظرتون برسه دو متد , با ساخت آبجکت , همزمان اجرا شدن ولی دلیل اجرای destructor به پایان رسیدن اسکریپت هست.
واسه نشون دادن این مسئله , یک مثال دیگه میزنم:
class Example { public function __construct() { print "In constructor<br>"; $this->name = "Example"; } public function __destruct() { echo "Destroying " . $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 "In constructor<br>";
$this->name = "Example";
}
function __destruct()
{
echo "Destroying " . $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@yahoo.com'; echo $obj->name . ' ' . $obj->family . ' ' . $obj->age . ' ' . $obj->email; // Mohsen Movahed 23
email جزو ایندکس ها نیست , بنابراین مقدار دهی نمیشود.
* به شکل های مختلف و اعتبار سنجی ها متفاوت میتونید این دو متدو پیاده سازی کنید.
Call :
وقتی توسط یک آبجکت , متدی رو فراخوانی کنیم که در کلاس مورد نظر وجود نداشته باشد , متد call__ اجرا میشود.
دو آرگومان دارد:
- نام متد
- آرگومان های ارسالی
class MethodTest { public function __call($method, $arguments) { // Note: value of $mthod is case sensitive. echo "Calling object method <strong>'$method'</strong> with arguments:<br>"; 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 "Calling static method <strong>'$method'</strong> with arguments: "
. implode(', ', $arguments) . PHP_EOL; } } MethodTest::runTest('in static context');
نتیجه:
Calling static method 'runTest' with arguments: in static context
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .