博主信息
博文 81
粉丝 1
评论 0
访问量 146920
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
tp中的app()助手函数是如何获取对象的?
有什么是忘不了的的博客
原创
1776人浏览过

tp给我们提供啦一个容器的概念,用来储存我们生产的类实例。在下次需要使用类实例时可以快速获取。

那app()助手函数是如何工作的:    

    通过查看助手文件得到他其实调用的是:Container::get()方法。

    function app($name = 'think\App', $args = [], $newInstance = false)
    {
        return Container::get($name, $args, $newInstance);
    }

    我们在去看Container::get()方法。

    public static function get($abstract, $vars = [], $newInstance = false)
    {
        //通过getInstance方法创建一个当前容器的实例(单例模式)再去调用make()方法
        return static::getInstance()->make($abstract, $vars, $newInstance);
    }

    我们来看make()方法:这个方法很重要,门面其实也是通过这个方法来创建对象。

    public function make($abstract, $vars = [], $newInstance = false)
    {
        if (true === $vars) {
            // 总是创建新的实例化对象
            $newInstance = true;
            $vars        = [];
        }
        static $i = 0;
        $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;
        //通过容器获取类的对象
        if (isset($this->instances[$abstract]) && !$newInstance) {
//            echo '容器中'.$i++.'<br>';
            return $this->instances[$abstract];
        }
            //通过反射创建类的对象
        if (isset($this->bind[$abstract])) {
            $concrete = $this->bind[$abstract];
            if ($concrete instanceof Closure) {
                $object = $this->invokeFunction($concrete, $vars);
                echo '反射'.$i++.PHP_EOL;
            } else {
                $this->name[$abstract] = $concrete;
                return $this->make($concrete, $vars, $newInstance);
            }
        } else {
            echo '反射'.$i++.PHP_EOL;
            $object = $this->invokeClass($abstract, $vars);
        }

        if (!$newInstance) {
            $this->instances[$abstract] = $object;
        }

        return $object;
    }

我为了证明app()在调用的时候是通过容器来获取对象的还是通过反射来获取对象的,在这个类中定义了一个:static $i = 0;和echo '反射'.$i++.PHP_EOL;来输出调用的方法和次数。方便观察。

当我的方法为空时:

(TPBSPE)VGJ`MBK4ZH[IGL9.png

输出为:

W8({%TRHB`02[UC@WN0TT$C.png

为什么会使出  17次的放射呢?

因为在框架初始化的时候会来获取一些默认的类对象(大概是这个意思)。所以这前17次输出都和我们没有关系

现在我在方法里调用一次我自己定义的一个类文件。

J6GWX4O3}X$O7W3HYK2ZIL3.png

再看输出

50T]]L@V{OB5V_25(%IS)EG.png

这是输出多啦一次 ‘反射’这说明当我们通过app()来获取一个我们未向容器注册过的类的时候,他会通过我们提供的命名空间,用反射来创建这个类的对象。

当我们调用两次app()来获取相同的类对象时:

    public function lize(){
//        bind('Redis',new \Redis);
        $redis = app('Redis');
        $redis = app('Redis');
    }

再看输出:

50T]]L@V{OB5V_25(%IS)EG.png并没有多输出一次‘反射’,这说明我们第二次调用的时候并没有通过反射来获取类对象。而是做的容器。

总结:

    当我们通过app()来获取一个类对象时,先会在容器里获取,获取不到去通过反射来获取。反射获取对象成功后,在吧这个对象放到容器里。下次获取的时候直接去容器里获取。(去不去容器里获取还可以通过,app()的第二个参数来决定,当为true时就不会走容器,不管容器里有没有。)








本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学