laravel-依賴注入源碼解析

<?php
//php7版本+
//依賴注入案例
//共三個版本
//1.原理版本
//2.面向過程版本
//3.外觀模式版本

class Category{

}
class Good {
    protected $category;
    public function __construct(Category $category)
    {
        $this->category = $category;
    }
}
class Order {

}
class Cart{
    protected $good;
    protected $order;
    public function __construct(Good $good, Order $order)
    {
        $this->good = $good;
        $this->order = $order;
    }
    public function run()
    {
        echo 'running';
    }
}
/******************************************原理版本start*****************************/
//Cart映射
$reflectClass = new ReflectionClass('Cart');
//獲取類的構造結構
$construct = $reflectClass->getConstructor();
//類的依賴
$dependencies = $construct->getParameters();

$denpendentInstances = [];
foreach ($dependencies as $dependent)
{
    if ($dependent instanceof ReflectionParameter
        //依賴名
        && ($dependentName = $dependent->getClass()->getName())
        && class_exists($dependentName)
    )
    {
        //由於依賴裏可能有其他依賴,所以這裏得考慮遞歸實例化依賴
        //實例依賴
//        $denpendentInstances[] = new $dependentName;
    }
}

//實例化具體類
//$cart->run(); //輸入running


/*****************************************************面向過程版本*****************************/

//面向過程版本
function make($class)
{
    //Cart映射
    $reflectClass = $class instanceof ReflectionClass ? $class : new ReflectionClass($class);
    //獲取類的構造結構
    $construct = $reflectClass->getConstructor();
    //依賴數組
    $denpendentInstances = [];

    if ($construct)
    {
        //類的依賴
        $dependencies = $construct->getParameters();


        foreach ($dependencies as $dependent)
        {
            if ($dependent instanceof ReflectionParameter
                //依賴名
                && ($dependentName = $dependent->getClass()->getName())
                && class_exists($dependentName)
            )
            {
                $denpendentInstances[] = make($dependentName);
            }
        }
    }


    return $reflectClass->newInstanceArgs($denpendentInstances);
}

$cart = make('Cart');
$cart->run(); //輸出running
//die;


/*************************************************外觀模式封裝版本**********************************/
//面向對象版本
class MakeClass{
    /**實例化類
     * @param $className 類名
     * @return object 返回實例對象
     * @throws Exception
     */
    public function make($className)
    {
        $reflectClass = $this->getReflectClass($className);
        if (!$reflectClass->isInstantiable())
        {
            throw new Exception('類無法生成');
        }
        $dependents = $this->getDependents($reflectClass);
        return $reflectClass->newInstanceArgs($dependents);
    }

    /**獲取映射類
     * @param $className
     * @return ReflectionClass
     * @throws ReflectionException
     */
    public function getReflectClass($className) : ReflectionClass
    {
        return $className instanceof ReflectionClass ? $className : new ReflectionClass($className);
    }

    /**獲取映射類的依賴
     * @param ReflectionClass $reflectClass
     * @return array
     */
    public function getDependents(ReflectionClass $reflectClass) : array
    {
        $construct = $reflectClass->getConstructor();
        if (!$construct)
        {
            return [];
        }
        //類的依賴
        $dependencies = $construct->getParameters();

        $denpendentInstances = [];
        foreach ($dependencies as $dependent)
        {
            //遞歸,依賴裏的依賴
            $denpendentInstances[] = $this->make(
                //依賴名稱
                $this->getDependentClassName($dependent)
            );
        }
        return $denpendentInstances;
    }

    /**獲取依賴名稱
     * @param ReflectionParameter $reflectionParameter
     * @return string
     */
    public function getDependentClassName(ReflectionParameter $reflectionParameter) :string
    {
        $class= $reflectionParameter->getClass();
        return $class ? $class->getName() : '';
    }
}

$make = new MakeClass();
$cart = $make->make('Cart');
$cart->run(); //輸出的running

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章