یک سری متد پیشفرض در هستهٔ زبان پیاچپی وجود دارند که نام آنها با علائم __
شروع میگردد که این دست متدها تحت عنوان Magic (جادویی) شناخته میشوند که ()construct__
یکی از رایجترین آنها است که در آموزش گذشته با کارکرد آن آشنا شدیم. در این آموزش، قصد داریم تا برخی از دیگر متدهای مَجیک در زبان پیاچپی را مورد بررسی قرار دهیم اما پیش از هر چیز، داخل پوشهٔ oop
پوشهای تحت عنوان magic-methods
ساخته و ساختار پروژههایی که در آموزشهای گذشته نوشتیم را داخل آن ایجاد میکنیم.
آشنایی با مَجیک متد ()set__
این مَجیک متد در مواقعی کاربرد دارد که بخواهیم پراپرتیهای کلاس را مقداردهی کنیم. برای این منظور، کلاس User
را به صورت زیر میسازیم:
<?php
namespace SokanAcademy;
class User
{
public $info = [];
public function __set($name, $value)
{
$this->info[$name] = $value;
}
}
داخل بدنهٔ کلاس User
یک پراپرتی از جنسِ آرایه تحت عنوان info$
ساختهایم که هیچ مقدار پیشفرضی ندارد. سپس مَجیک متد ()set__
را نوشته و دو پارامتر ورودی برایش در نظر میگیریم تحت عناوین name$
و value$
که این دو پارامتر برای کارکرد صحیح این مَجیک متد الزامی هستند. سپس داخل این متد پراپرتی info$
را فراخوانی کرده و پارامتر name$
را به عنوان کلیدی جدید برای آرایهٔ مذکور در نظر گرفته و پارامتر value$
را به عنوان مقدار آن قملداد کردهایم. حال فایل index.php
را به صورت زیر تکمیل میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
$user->fName = "Behzad";
$user->lName = "Moradi";
var_dump($user->info);
همانطور که میبینیم، آبجکتی تحت عنوان user$
از روی کلاس User
ساخته سپس نام این آبجکت را نوشته و پس از درج علائم <-
نامی دلخواه همچون fName
در نظر گرفته و مقدار آن را برابر با یک استرینگ قرار دادهایم (به همین منوال، lName
را نیز سِت کردهایم.) در واقع، در مثال فوق نامهای fName
و lName
به پارامتر ورودی name$
در متد ()set__
منتسب شده و به عنوان کلیدهای آرایهٔ info$
در نظر گرفته خواهند شد و استرینگهایی هم که به عنوان مقادیر این دو کلید در نظر گرفته شدهاند نیز با پراپرتی value$
این متد مَچ شده و به عنوان مقادیر اِلِمانهای آرایه در نظر گرفته خواهند شد. در نهایت هم با استفاده از دستور ()var_dump
مقادیر پراپرتی info$
را چاپ کردهایم به طوری که خواهیم داشت:
array(2) {
["fName"]=>
string(6) "Behzad"
["lName"]=>
string(6) "Moradi"
}
میبینیم که کلیدهای مد نظرمان با مقادیرم متناظرشان که پیش از این وجود خارجی نداشتند به درستی ایجاد شدهاند.
آشنایی با مَجیک متد ()get__
این مَجیک متد همانطور که از نامش مشخص است، به منظور دریافت یک پراپرتی میتواند مورد استفاده قرار گیرد که برای درک بهتر سازوکار آن، کلاس User
را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User
{
public $info = [];
public function __set($name, $value)
{
$this->info[$name] = $value;
}
public function __get($name)
{
return $this->info[$name];
}
}
مَجیک متد ()get__
یک پارامتر ورودی الزامی دارا است که در این مثال نامی همچون name$
برایش در نظر گرفتهایم و داخل این متد هم دستور دادهایم تا کلید متناظر با این پارامتر از پراپرتی info$
ریترن گردد. جهت تست این متد، فایل index.php
را به صورت زیر آپدیت میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
$user->fName = "Behzad";
$user->lName = "Moradi";
// var_dump($user->info);
echo $user->fName;
میبینیم که در خط نهم کلید مد نظرمان که fName
است را به آبجکت user$
منتسب کردهایم و دستور دادهایم تا مقدار آن چاپ گردد که با اجرای این اسکریپت، استرینگ مربوطه چاپ خواهد شد. در واقع، به محض این که مفسر پیاچپی به دستور ;echo $user->fName
برسد، مَجیک متد ()get__
به صورت خودکار فراخوانی خواهد شد.
در ارتباط با مَجیک متدهای ()set__
و ()get__
این نکته را همواره باید به خاطر داشت که این متدها صرفاً زمانی به صورت خودکار فراخوانی خواهند شد که با پراپرتیهایی سروکار داشته باشیم که از قبل وجود ندارند و چنانچه یک پراپرتی از قبل وجود داشته باشد، این متدها هرگز اجرا نخواهند شد. برای روشنتر شدن این مسئله، کلاس User
را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User
{
public $info = [];
public function __set($name, $value)
{
die ("We`re in __set()");
// $this->info[$name] = $value;
}
public function __get($name)
{
return $this->info[$name];
}
}
همانطور که ملاحظه میشود، دستور قبلی داخل متد ()set__
را کامنت کرده و در عوض از دستور ()die
استفاده کردهایم تا بتوانیم رفتار پیاچپی را رصد کنیم. اکنون اگر فایل index.php
را با کدهای زیر مبنا قرار دهیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
$user->fName = "Behzad";
$user->lName = "Moradi";
به عنوان خروجی خواهیم داشت:
We`re in __set()
در واقع، میبینیم که مَجیک متد ()set__
فراخوانی شده است چرا که قصد داریم پراپرتیهایی را ایجاد کنیم که از قبل وجودِ خارجی نداشتهاند. حال کلاس User
را به صورت زیر تغییر میدهیم:
<?php
namespace SokanAcademy;
class User
{
public $info = [];
public function __set($name, $value)
{
$this->info[$name] = $value;
}
public function __get($name)
{
die("We`re in __get()");
// return $this->info[$name];
}
}
میبینیم که این بار دستور ()die
را داخل متد ()get__
نوشتهایم. اکنون فایل index.php
را به صورت زیر آپدیت میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
$user->fName = "Behzad";
$user->lName = "Moradi";
echo $user->fName;
در حقیقت، در خط هشتم قصد داریم تا مقدار پراپرتیای که از قبل وجود نداشته است را فراخوانی کنیم به طوری که در خروجی خواهیم داشت:
We`re in __get()
میبینیم که مَجیک متد ()get__
به درستی فراخوانی شده است. در عین حال، توجه داشته باشیم که اگر یک پراپرتی از قبل داخل کلاس تعریف شده باشد و بخواهیم به آن دست یابیم، این متد هرگز اجرا نخواهد شد به طوری که مثلاً داریم:
<?php
namespace SokanAcademy;
class User
{
public $info = [];
public $tmpProperty = "This is temporary property";
public function __set($name, $value)
{
$this->info[$name] = $value;
}
public function __get($name)
{
die ("We`re in __get()");
// return $this->info[$name];
}
}
یک پراپرتی جدید تحت عنوان tmpProperty$
با یک مقدار پیشفرض ساختهایم. حال مجدد به فایل index.php
باز میگردیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
$user->fName = "Behzad";
$user->lName = "Moradi";
echo $user->tmpProperty;
و به عنوان خروجی هم خواهیم داشت:
This is temporary property
میبینیم با توجه به این که پراپرتی tmpProperty$
از قبل وجود داشته است، مَجیک متد ()get__
هرگز اجرا نخواهد شد.
همچون متد ()construct__
، متدهای ()set__
و ()get__
حتی اگر به صورت دستی هم کال نشوند، در صورتی که قصد کار با یک پراپرتی را داشته باشیم که وجودِ خارجی ندارد، به صورت خودکار توسط مفسر پیاچپی کال خواهند شد که برای روشنتر شدن این مسئله، فایل جدیدی تحت عنوان User2.php
داخل پوشهٔ classes
ساخته و آن را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User2
{
}
میبینیم که این کلاس حاوی کد خاصی نیست. حال به فایل index.php
بازگشته و آن را به صورت زیر آپدیت مینماییم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
// $user = new SokanAcademy\User();
// $user->fName = "Behzad";
// $user->lName = "Moradi";
// echo $user->tmpProperty;
$userTwo = new SokanAcademy\User2();
$userTwo->job = "Developer";
$userTwo->programmingLanguage = "PHP";
echo $userTwo->job;
echo $userTwo->programmingLanguage;
ابتدا کدهای قبلی را کامنت کرده سپس آبجکتی تحت عنوان userTwo$
از روی کلاس User2
ساخته سپس در خطوط یازدهم و دوازدهم سعی کردهایم تا دو پراپرتی جدید تحت عناوین job
و programmingLanguage
بسازیم و مقادیری را نیز برای آنها در نظر گرفتهایم. در واقع، این دو خط از کد منجر به فراخوانی متد ()set__
خواهند شد زیرا پیش از این چنین پراپرتیهایی وجود نداشتهاند. در ادامه، با استفاده از دستور echo
قصد داریم تا مقدار این پراپرتیها را نمایش دهیم و نیاز به توضیح نیست که به منظور اجرای خطوط سیزدهم و چهاردهم، متد ()get__
فراخوانی خواهد شد.
در پایان لازم به یادآوری است که جهت آشنایی با دیگر مَجیک متدهای زبان برنامهنویسی پیاچپی، میتوانید به لینک Magic Methods در سایت رسمی زبان پیاچپی مراجعه نمایید.