رفلکشن در پی اچ پی Reflection in PHP بخش دوم

در قسمت قبل دیدیم که با رفلکشن ReflectionFunction می‌توانیم اجزای یک تابع را بررسی کنیم و پارامتر‌های تابع هم از نوع رفلکشن ReflectionParameter هستند و میتوان اجزای آنها را هم بررسی کرد. در این بخش یک کلاس تعریف میکنیم و آن را بررسی میکنیم.
ابتدا یک کلاس به نام Person را تعریف میکنیم

<?php
 /** * This is simple description about class * */
 class Person 
{
 public $name;
 private $age;

 public function __construct()
   {
      $this->name = 'Anonymous';
   }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setAge($age)
    {
        $this->age = $age;
    }

    public function getAge()
    {
        return $this->age;
    }
}

$rc = new ReflectionClass('Person');

echo $rc->getName(); // Person  
// نام کلاس را بر میگرداند

// echo $rc->getDocComment();
// /**
// * This is simple description about  class 
// *
// */

// توضیحات بالای کلاس را برمیگرداند 

$methods = $rc->getMethods();
// print_r($methods); 
//   هستند ReflectionMethod لیستی از متد های تابع را برمیگرداند که از نوع 
foreach ($methods as $method) {
    echo $method->getName(); 
    //    دقت میکنید که به یک ابجکت از نوع رفلکشن متد دسترسی داریم و از توابع مربط به خودش میتوانیم استفاده کنیم 
    echo "\n";
}

همان گونه که در کد بالا می بینبد می توانیم اجزاء کلاس و ساختار هر بخش آن را بررسی کنیم و نام کلاس getName و با استفاده از متد getMethods متد های کلاس را ببینیم که این متد برای یک آرایه از نوع ReflectionMethod بر می‌گرداند.
ReflectionMethodساختاری شبیه به ReflectionFunction دارد و  هر دو اینها از کلاس ReflectionFunctionAbstract ارث بری کرده اند

ReflectionFunctionAbstract implements Reflector
ReflectionFunction extends ReflectionFunctionAbstract implements Reflector
ReflectionMethod extends ReflectionFunctionAbstract implements Reflector

کلاس ReflectionFunctionAbstract شامل متد های زیر است

final private __clone ( void ) : void
public getClosureScopeClass ( void ) : ReflectionClass
public getClosureThis ( void ) : object
public getDocComment ( void ) : string
public getEndLine ( void ) : int
public getExtension ( void ) : ReflectionExtension
public getExtensionName ( void ) : string
public getFileName ( void ) : string
public getName ( void ) : string
public getNamespaceName ( void ) : string
public getNumberOfParameters ( void ) : int
public getNumberOfRequiredParameters ( void ) : int
public getParameters ( void ) : array
public getReturnType ( void ) : ReflectionType
public getShortName ( void ) : string
public getStartLine ( void ) : int
public getStaticVariables ( void ) : array
public hasReturnType ( void ) : bool
public inNamespace ( void ) : bool
public isClosure ( void ) : bool
public isDeprecated ( void ) : bool
public isGenerator ( void ) : bool
public isInternal ( void ) : bool
public isUserDefined ( void ) : bool
public isVariadic ( void ) : bool
public returnsReference ( void ) : bool
abstract public __toString ( void ) : void

ReflectionFunction متد های بالا را دارد اما ReflectionMethod متد های زیر  را علاوه بر متد های بالا دارد

public static export ( string $class , string $name [, bool $return = FALSE ] ) : string
public getClosure ( object $object ) : Closure
public getDeclaringClass ( void ) : ReflectionClass
public getModifiers ( void ) : int
public getPrototype ( void ) : ReflectionMethod
public invoke ( object $object [, mixed $... ] ) : mixed
public invokeArgs ( object $object , array $args ) : mixed
public isAbstract ( void ) : bool
public isConstructor ( void ) : bool
public isDestructor ( void ) : bool
public isFinal ( void ) : bool
public isPrivate ( void ) : bool
public isProtected ( void ) : bool
public isPublic ( void ) : bool
public isStatic ( void ) : bool
public setAccessible ( bool $accessible ) : void

با نگاهی متد های اضافه می بینم چه ویژگی هایی یک متد را از فانکشن متمایز میکند.

ایده :‌ به لیست متد ها نگاه کنید  و فکر کنید هر کدام چه کاربردی دارند یا اینکه کدام با کاربرد کدام آشنا نیستید.

به متد setAccessible دقت کنید، آیا  واقعا میتوانیم دسترسی یک متد را تغییر دهیم ؟ (بررسی می‌کنیم)

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

<?php

class Math 
{
    public static function power($num)
    {
            return "Power {$num} is " . self::calcPower($num);
    }

    private static function calcPower($num)
    {
        return $num * $num;
    }
}

echo Math::power(2);
// Power 2 is 4

// echo Math::calcPower(2);
// PHP Fatal error:  Uncaught Error: Call to private method Math::calcPower() from context ''

همان طور که انتظار داریم متد private را نمی توانیم خارج از خود کلاس صدا بزنیم(دسترسی نداریم)، اما با استفاده از رفلکشن می توانیم این کار را انجام دهیم

$rm = new ReflectionMethod('Math', 'calcPower');

$rm->setAccessible(true);

echo  $rm->invoke(null, 2); // صدا زدن متد استاتیک
// 4

با استفاده از setAccessible و invoke توانستیم یک متد private  را خارج از کلاس صدا بزنیم. (جالب بود نه)

برای پروپرتی هم ReflectionProperty داریم و می توانیم دسترسی ها را تغییر دهیم و از آنها هم استفاده کنیم.

در پایین لیست رفلکشن ها را و کلاس ها و اینترفیس های مربوط به رفلکشن‌ها را میبینیم که می توانیم یک دید کلی در مورد آنها پیدا کنیم.

Reflector 
 ReflectionClassConstant implements Reflector
 ReflectionProperty implements Reflector
 ReflectionClass implements Reflector
 ReflectionObject extends ReflectionClass implements Reflector

 ReflectionZendExtension implements Reflector
 ReflectionExtension implements Reflector 

 ReflectionFunctionAbstract implements Reflector 
 ReflectionFunction extends ReflectionFunctionAbstract implements Reflector 
 ReflectionMethod extends ReflectionFunctionAbstract implements Reflector
 
 ReflectionType 
 ReflectionNamedType extends ReflectionType

 ReflectionParameter implements Reflector 
 
 ReflectionGenerator 
 Reflection
 ReflectionException extends Exception

احتمالا بررسی ReflectionObject هم جالب خواهد بود. (تمرین)

فایل های این بخش

در بخش بعد در مورد کاربرد رفلکش‌ها می نویسم و بحث رفلکشن را تمام میکنیم.

 


دیدگاه‌ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *