用户
 找回密码
 入住 CI 中国社区
搜索
查看: 3146|回复: 3
收起左侧

[核心代码 Core] 整合PHP-DI,让CI用上依赖注入

[复制链接]
发表于 2019-12-22 14:04:37 | 显示全部楼层 |阅读模式
本帖最后由 andel 于 2019-12-22 14:04 编辑

最近我捣鼓了一下CI3,在不改动框架核心文件和不改变框架原有功能的前提下,把PHP-DI整合进来了,让在CI3.x上构建的项目可以使用依赖注入。

PHP复制代码
 
class MY_Hooks extends CI_Hooks
{
    public function __construct()
    {
        parent::__construct();
    }
 
    /**
     * The instance of DI ContainerBuilder
     * @var [DI\ContainerBuilder] 用于存放容器建造器实例(单例)
     */

    private static $di_container_builder;
 
    /**
     * The instance of CI_Controller
     * @var [CI_Controller]  CodeIgniter 对象(单例)
     */

    private static $ci;
 
    /**
     * Call Hook
     *
     *
     * @uses        CI_Hooks::_run_hook()
     *
     * @param        string        $which        Hook name
     * @return        bool        TRUE on success or FALSE on failure
     */

    public function call_hook($which = '')
    {
        if ($which === 'post_controller_constructor')
        {
            // 由于实现依赖注入后,为了实现松耦合,控制器不再继承CI_Controller,但为了仍可以访问 CodeIgniter资源,需要实例化CI_Controller类
            if (self::$ci == NULL) {
                self::$ci = new CI_Controller;
            }
            // 实例化构建器
            if (self::$di_container_builder == NULL) {
                self::$di_container_builder = new DI\ContainerBuilder;
            }                        
            // 构建DI容器
            $container = self::$di_container_builder->addDefinitions(APPPATH.'config/di.php')->build();
            // 重载 Controller实例$CI,改由DI容器生成,从而在所有控制器中实现依赖注入
            global $CI, $class;                                
            $CI = $container->get($class);
        }
                /**
                 * 以下与父类call_hook方法一致
                 */

                if ( ! $this->enabled OR ! isset($this->hooks[$which]))
                {
                        return FALSE;
                }
 
                if (is_array($this->hooks[$which]) && ! isset($this->hooks[$which]['function']))
                {
                        foreach ($this->hooks[$which] as $val)
                        {
                                $this->_run_hook($val);
                        }
                }
                else
                {
                        $this->_run_hook($this->hooks[$which]);
                }
 
                return TRUE;
    }
 
}
 
 
复制代码


源码获取:https://github.com/Xandel/DI_CI
Demo演示:
http://andel.xlphp.net
有兴趣的朋友可以参考Demo,通过以下几个步骤整合CI和PHP-DI:
1. composer install 或 composer update(composer.json的设置请参考Demo的composer.json文件);
2. 把框架核心扩展文件MY_Hooks.php安装到 application/core 路径下;
3. 把DI容器配置文件di.php安装到 application/config 路径下。
这样就可以了,您可以在控制器里使用依赖注入了。控制器的依赖以及依赖的依赖均由DI容器注入,实现了高度松耦合。
要注意的一点是,不能在控制器的构造函数里使用参数type-hint的方式注入依赖,建议使用属性注入。关于DI容器的使用方法,欢迎访问PHP-DI官网获取更多信息。
以下这篇文章有更详细的解析:https://zhuanlan.zhihu.com/p/98644060
欢迎讨论。


评分

参与人数 1威望 +5 收起 理由
Hex + 5 赞一个!

查看全部评分

发表于 2020-2-21 20:21:48 | 显示全部楼层
woc  对你的如滔滔江水绵延不绝
发表于 2020-2-24 18:03:28 | 显示全部楼层
大神就是大神
发表于 2020-4-27 17:21:52 | 显示全部楼层
啥时候整一个ci4版本的

本版积分规则