zoukankan      html  css  js  c++  java
  • yii2框架随笔27

    <?php
        /**
         * Creates an instance of the specified class.
         * 创建指定类的实例。
         * This method will resolve dependencies of the specified class, instantiate them, and inject
         * them into the new instance of the specified class.
         * 该方法将解决指定类的实例化,依赖他们,并注入它们进入指定类的新实例。
         * @param string $class the class name
         * @param array $params constructor parameters
         * @param array $config configurations to be applied to the new instance
         * @return object the newly created instance of the specified class
         */
        protected function build($class, $params, $config)
        {
            /* @var $reflection ReflectionClass */
            // 先获取类的反射的实例和要依赖的参数(Instance的数组)
            list ($reflection, $dependencies) = $this->getDependencies($class);
            // 用传入的参数去替换掉默认的参数
            foreach ($params as $index => $param) {
                $dependencies[$index] = $param;
            }
            // 将Instance实例转化成相应的id中存储的类名的实例,即参数的真正的实例
            $dependencies = $this->resolveDependencies($dependencies, $reflection);
            if (empty($config)) {
                // ReflectionClass::newInstanceArgs — 从给出的参数创建一个新的类实例
                // 如果$config是空,直接创建一个新的类的实例返回
                return $reflection->newInstanceArgs($dependencies);
            }
            // ReflectionClass::implementsInterface — 检查它是否实现了一个接口(interface)
            // config不为空
            if (!empty($dependencies) && $reflection->implementsInterface('yiiaseConfigurable')) {
                // 依赖不为空而且class实现了 yiiaseConfigurable 的接口
                // 实现了 yiiaseConfigurable 的接口,就意味着类的构造函数的最后一个参数是$config
                // set $config as the last parameter (existing one will be overwritten)
                $dependencies[count($dependencies) - 1] = $config;
                return $reflection->newInstanceArgs($dependencies);
            } else {
                $object = $reflection->newInstanceArgs($dependencies);
                // 循环$config,将$config的键值对赋给相应的类的实例
                foreach ($config as $name => $value) {
                    $object->$name = $value;
                }
                return $object;
            }
        }
        /**
         * Merges the user-specified constructor parameters with the ones registered via [[set()]].
         * 将用户指定的构造函数参数通过[set()]注册。
         * @param string $class class name, interface name or alias name
         * @param array $params the constructor parameters
         * @return array the merged parameters
         */
        protected function mergeParams($class, $params)
        {
            if (empty($this->_params[$class])) {
                // 如果_params中不存在,就直接返回$params
                return $params;
            } elseif (empty($params)) {
                // 如果_params中存在,且params为空,就返回_params中的内容
                return $this->_params[$class];
            } else {
                // 如果都不为空,就将两者合并起来,以$params为主
                $ps = $this->_params[$class];
                foreach ($params as $index => $value) {
                    $ps[$index] = $value;
                }
                return $ps;
            }
        }
        /**
         * Returns the dependencies of the specified class.
         * 返回指定的类的依赖关系。
         * @param string $class class name, interface name or alias name
         * @return array the dependencies of the specified class.
         */
        protected function getDependencies($class)
        {
            if (isset($this->_reflections[$class])) {
                return [$this->_reflections[$class], $this->_dependencies[$class]];
            }
            $dependencies = [];
            $reflection = new ReflectionClass($class);
            // 获取类的构造方法
            $constructor = $reflection->getConstructor();
            if ($constructor !== null) {
                // 获取构造方法的参数,并将其实例化
                foreach ($constructor->getParameters() as $param) {
                    if ($param->isDefaultValueAvailable()) {
                        // 如果有defalut值,就直接将默认值放入依赖中
                        $dependencies[] = $param->getDefaultValue();
                    } else {
                        // 否则,就先获取param的ReflectionClass
                        $c = $param->getClass();
                        // 然后通过getName获取类的名称(带namespace),生成一个Instance的实例
                        // Instance中有个id属性,标记了类的名称
                        $dependencies[] = Instance::of($c === null ? null : $c->getName());
                    }
                }
            }
            // 将类的反射实例和参数依赖的实例分别缓存到_reflections和_dependencies数组中
            $this->_reflections[$class] = $reflection;
            $this->_dependencies[$class] = $dependencies;
            return [$reflection, $dependencies];
        }
        /**
         * Resolves dependencies by replacing them with the actual object instances.
         * 将Instance的实例替换成参数本身应该的实例
         * @param array $dependencies the dependencies
         * @param ReflectionClass $reflection the class reflection associated with the dependencies
         * @return array the resolved dependencies
         * @throws InvalidConfigException if a dependency cannot be resolved or if a dependency cannot be fulfilled.
         */
        protected function resolveDependencies($dependencies, $reflection = null)
        {
            foreach ($dependencies as $index => $dependency) {
                // 依赖是Instance的实例,才做处理
                if ($dependency instanceof Instance) {
                    if ($dependency->id !== null) {
                        // id不为空,就使用get方法去获取它的实例
                        $dependencies[$index] = $this->get($dependency->id);
                    } elseif ($reflection !== null) {
                        // 找出缺少的参数名称,以及其所在的类名
                        $name = $reflection->getConstructor()->getParameters()[$index]->getName();
                        $class = $reflection->getName();
                        throw new InvalidConfigException("Missing required parameter "$name" when instantiating "$class".");
                    }
                }
            }
            return $dependencies;
        }
    }
  • 相关阅读:
    HDU 4278 Faulty Odometer 8进制转10进制
    hdu 4740 The Donkey of Gui Zhou bfs
    hdu 4739 Zhuge Liang's Mines 随机化
    hdu 4738 Caocao's Bridges tarjan
    Codeforces Gym 100187M M. Heaviside Function two pointer
    codeforces Gym 100187L L. Ministry of Truth 水题
    Codeforces Gym 100187K K. Perpetuum Mobile 构造
    codeforces Gym 100187J J. Deck Shuffling dfs
    codeforces Gym 100187H H. Mysterious Photos 水题
    windows服务名称不是单个单词的如何启动?
  • 原文地址:https://www.cnblogs.com/taokai/p/5470333.html
Copyright © 2011-2022 走看看