1. 程式人生 > >PHP進階3 反射

PHP進階3 反射

                    不積跬步無以至千里不積小流無以成江海


反射機制的強大在於,在很多情況下可以使程式碼更加高效
例如不知道事先需要例項化哪個類,而是在執行時根據動態資訊確定
對於這種情況可以通過反射機制獲取需要例項類的建構函式資訊並完成相應的例項化

class A
{
    public function call()
    {
        echo 'hello world';
    }
}

//  ReflectionClass 類報告了一個類的有關資訊
$ref = new ReflectionClass('A');

//  ReflectionClass::newInstanceArgs — 從給出的引數建立一個新的類例項
$inst = $ref->newInstanceArgs();

$inst->call();
laravel框架中,服務容器解析服務的過程中就用到了反射機制
//  根據給定的類初始化一個具體事例

public function build($concrete, array $parameters = [])
{

    /*
     * 解析服務是通過build()函式實現的
     * 查詢對應的服務是否被服務提供者註冊為例項或提供服務的匿名函式
     * 如果是則直接進行服務解析
     */

    if ($concrete instanceof Closure) {
        return $concrete($this, $parameters);
    }

    /*
     * 如果服務名稱沒有相應的服務繫結,通過反射機制來動態建立服務
     */

    //  建立一個反射例項,$concrete是類的名稱
    $reflector = new ReflectionClass($concrete);

    //  檢查類是否可例項化
    if (!$reflector->isInstantiable()) {
        $message = "Target [$concrete] is not instantiable .";
        throw new BindingResolutionContractException($message);
    }

    $this->buildStack[] = $concrete;

    //  獲取類的構造方法,當該類存在建構函式時,返回一個ReflecttionMethod物件,相當於獲取建構函式的反射類
    $constructor = $reflector->getConstructor();

    //  如果不存在建構函式直接例項化該類
    if (is_null($constructor)) {
        array_pop($this->buildStack);
        return new $concrete;
    }

    //  獲取建構函式的依賴的輸入引數
    $dependencies = $constructor->getParameters();

    //  獲取直接提供的實參
    $parameters = $this->keyParamtersByArgument($dependencies, $parameters);

    //  未直接提供的實參
    $instances = $this->getDependencies($dependencies, $parameters);

    array_pop($this->buildStack);

    //  從給出的引數建立一個新的類例項
    return $reflector->newInstanceArgs($instances);

}

未完待續,繼續更新......