سلام. در این پست متد های جادویی (Magic Methods) رو معرفی میکنم.
برای آشنایی و اطلاعات بیشتر در مورد هر تابع لینک مرجع تابع از سایت php.net قرار گرفته.
توابع این پست به تدریج کاملتر خواهد شد.

 

 

Constructor :

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

 



 

Destructor :

متد جادویی دیگری که در 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__ در زمان مقدار دهی فیلدها اجرا خواهد شد.
دو آرگومان داره: 

  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@yahoo.com';

echo $obj->name . ' ' . $obj->family . ' ' . $obj->age . ' ' . $obj->email; // Mohsen Movahed 23


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

 



 

Call :

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

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

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

متد 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

 



 

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

محسن موحد | متفرقه , PHP , Javascript , Jquery , امنیت , پدر بزرگم | روز چهارشنبه ۱۹ فروردین ۱۳۹۴ - ۰۰:۲۸ | نظرات (1)
رضا پیری قدیم در روز پنجشنبه ۲۰ فروردین ۱۳۹۴ - ۰۱:۲۰ گفت:

دستت درد نکنه داداش عالیه. موفق باشی

نقل قول

فیلدهای * دار الزامی می باشند.