رفلکشن در PHP

رفلکشن یکی از قابلیت های مهمی هستش که اکثر زبان های برنامه نویسی مثل جاوا ، #C و PHP اون رو پشتیبانی میکنن.

با استفاده از رفلکشن میشه هنگام runtime ، بدون new کردن یک کلاس ، از تمامی زیر و بم اون کلاس مثل property , method , comment و... اون کلاس مطلع شد ، به متدهای اون کلاس دسترسی پیدا کرده و مقادیری رو پاس داد و توابع اون کلاس رو call کرد .

میشه return type متدها رو فهمید و حتی به property هایی که private هستن مقدار ست کرد .

از کاربردهای مهم رفلکشن در طراحی فریمورک خصوصا ORM هستش که قراره آبجکت ها رو توی دیتابیس ذخیره کنه ، دیتاها رو از پایگاه داده بخونه و به متدهای setter پاس بده و...

فرض کنید یک کلاس داریم به نام Article که دارای یک سری property و method هستش ، با استفاده از رفلکشن میخواههیم به این از این کلاس یک instance جدید درست کنیم ، متدها و پراپرتی هاش رو لیست کنیم و به اونها مقادیری رو set کنیم .

<?php

class Article{

private $title;

private $body;

public function getTitle()
{
return $this->title;
}

public function setTitle($title): void
{
$this->title = $title;
}

public function getBody()
{
return $this->body;
}

public function setBody($body): void
{
$this->body = $body;
}
}



حالا میتونیم با استفاده از reflection از زیر و بم این آبجکت مطلع بشیم .

try {
$reflection_class = new ReflectionClass(Article::class);

$object = $reflection_class->newInstance();
} catch (ReflectionException $e) {
print $e->getMessage();
}

میتونیم با کدهای زیر تمامی متدهای این کلاس رو لیست کنیم .

foreach ($reflection_class->getMethods() as $method) {
echo $method->getName() . PHP_EOL;
}

متدهای کلاس Article
متدهای کلاس Article

حالا اگه بخواهیم به متدهایی خاصی دسترسی داشته باشیم ، مثل متدهای setter که کارشون ست کردن دیتا هستش میتونیم از روش زیر استفاده کنیم .

foreach ($reflection_class->getMethods() as $method) {
if (substr($method->getName(), 0, 3) == "set") {
echo $method->getName() . PHP_EOL;
}
}

حالا میتونیم با روش زیر به متدهای setter این کلاس ، دیتا ، ست کنیم .

$data = [
"the title",
"Article Body"
];
$index = -1;
foreach ($reflection_class->getMethods() as $method) {
if (substr($method->getName(), 0, 3) == "set") {

if (!($method->isPublic())){
$method->setAccessible(true);

}
$index++;
$method->invoke($object, $data[$index]);
}
}

حالا خیلی راحت میتونیم متدهای getter رو صدا بزنیم .

foreach ($reflection_class->getMethods() as $method) {
if (substr($method->getName(), 0, 3) == "get") {
echo $object->{$method->name}().PHP_EOL;
}
}

خروجی
خروجی

به صورت دستی هم میشه به پراپرتی ها و متدها با استفاده از نوشتن صریح اسم اونها ، بهشون دسترسی پیدا کرد ، خصوصا میشه به پراپرتی های private دسترسی پیدا کنید و مقادیری را روی اونها set کنید .

try {
$property = new ReflectionProperty("Article", "title");
} catch (ReflectionException $e) {
echo $e->getMessage();
}

$property->setAccessible(true);

$property->setValue($object,"this is new title");

echo $property->getValue($object);


اینها تنها چند نمونه ساده از reflection بود و میشه کارهایی به مراتب بیشتر و جالب تر را باهاش انجام داد .