(三)从零编写PHP容器-解决类重复依赖创建

项目源码

功能实现

  • 解决类重复依赖创建、解决相互依赖(A->B->A->B->...)、循环依赖(A->B->C->A->B->C->A->...)

代码实现 Container

    /**
     * 解决相互依赖及循环依赖判断
     * @param string $abstract
     * @param array $tmp
     * @return Closure|object
     * @throws ReflectionException
     */
    public function createObjectNoEach(string $abstract, array $tmp = [])
    {
        if ($tmpInstance = &$tmp[$abstract]) {
            return $tmpInstance;
        }
        $refClass = new ReflectionClass($abstract);
        if ($refClass->getName() === Closure::class) {
            return function (){};
        } elseif ($refClass->hasMethod('__construct')) {
            $_constructParams = array_map(function (ReflectionParameter $param) use ($abstract, $tmp) {
                if ($param->getClass()) {
                    if (array_key_exists($param->getClass()->getName(), $tmp)) {
                        throw new class('can not create a circular dependencies class object.') extends Exception implements ContainerExceptionInterface{ };
                    }
                    return $this->createObjectNoEach($param->getClass()->getName(), $tmp);
                } elseif ($param->isDefaultValueAvailable()) {
                    return $param->getDefaultValue();
                } elseif ($param->getType()) {
                    return [
                            'string' => '',
                            'int' => 0,
                            'array' => [],
                            'bool' => false,
                            'float' => 0.0,
                            'iterable' => [],
                            'callable' => function() {}
                        ][$param->getType()->getName()] ?? null;
                } else {
                    return null;
                }
            }, $refClass->getMethod('__construct')->getParameters());
        }
        return $tmpInstance = $refClass->newInstance(... ($_constructParams ?? []));
    }

实现思路

  • 通过存储自动创建实例对象,在参数列表中出现相同的类时判断为循环并抛出异常

添加代码

  1. 判断是否缓存有实例对象
if ($tmpInstance = &$tmp[$abstract]) {
    return $tmpInstance;
}
  1. 判断自动创建的类是否被创建过,如果被创建过则认为是递归,抛出异常
if (array_key_exists($param->getClass()->getName(), $tmp)) {
    throw new class('can not create a circular dependencies class object.') extends Exception implements ContainerExceptionInterface{ };
}
return $this->createObjectNoEach($param->getClass()->getName(), $tmp);
  1. 存储自动创建的类实例
return $tmpInstance = $refClass->newInstance(... ($_constructParams ?? []));

示例

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 7,890评论 2 9
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 12,943评论 0 13
  • 运海抟扶必借垂天之羽,乘流击汰必伫飞天之楫。在假期之际,适逢榆树电教馆组织该项活动,给我提供了一次再学习、...
    榆树112赵洪卫阅读 3,641评论 1 7
  • 今年的暑假过得累而充实,每天不仅要顶着大太阳去练车,而且还要忙着装修。真的特别的累,但是每周三的互加课让我觉得特别...
    宁都4077张金婷阅读 1,001评论 0 3
  • 一直觉得自己是个很脆弱的人,我有许多害怕的东西,怕黑怕鬼怕老师怕老妈怕陌生人,从来没觉得自己是个肆无忌惮的小孩,习...
    林木之鹿阅读 2,744评论 2 1