php - di 依赖注入实现的意义是什么?

 阿花-我们寝室的猫 发布于 2022-11-14 18:49

一般的 PHP 框架,一个应用 Application,生命周期大概是这样的:Request > Router / Url > Dispatch > Controller/Action [ > Service] > Model > [ > View] > Response,当然可能有些差别,多数无外乎这样。

那引入 di 注入的意义是什么呢?是为了把应用流程涉及的对象设计成组件来实现解耦?比如 RequestInterface / HttpRequest / CliRequest,RouterInterface / SimpleRouter / RegexRouter / MapRouter 等?

但是一个普通的带视图带数据库操作的请求大致流程大家都一样啊(ROR / J2EE / PHP MVC),即使是 restful 也是有 Router / Request / ControllerAction / Response 的,这解耦的意义是什么呢?解来解去,还得捞出来组个 MVC 流程。就好像 Router 妥妥的依赖 Request,那就手工注入喽?Router 构造函数参数是 RequestInterface $request 喽?当前应用入口决定注入何种 Request 对象喽?难不成哪天 Router 还依赖个奇怪的玩意不成?

难道说仅仅是为了 mock 方便?还是说为了不确定的将来?还是说有其它的原因。。。

6 个回答
  • 就是为了解耦啊,简单的MVC就按照你上面的流程根本无法完成解耦。模块之间的依赖依然非常严重。

    2022-11-14 19:08 回答
  • DI的前提是你需要一个统一的容器去承载你的bean,拥有这么一个容器的时候,你可以对里面的bean进行一些特殊的操作而且不用大篇幅的修改代码,难道这还不够吗?

    2022-11-14 19:08 回答
  • 没错,就是解耦。
    用个MVC就是解耦完成了?
    这是最低层次的解耦好吗?

    2022-11-14 19:08 回答
  • 依赖注入是面向对象编程里面用来解耦的设计模式.

    <?php
    class db {
        public static function get_db() {
            return new mysqli('127.0.0.1','user','pass','dbname',3306);
        }
    }
    class post {
        private $db;
        public function set_db($db){
            $this->db = $db;
        }
        public function get_post($id){
            return $this->db->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
        }
    }
    $post = new post();
    $post->set_db( db::get_db() ); //注入post类依赖的数据库连接对象,通过类名直接调用静态方法get_db
    $post->get_post(1024);

    对比下过程式的写法:

    <?php
    function db() {
        static $db; //静态变量避免重复连接
        if ($db) {
            return $db;
        } else {
            $db = new mysqli('127.0.0.1','user','pass','dbname',3306);
            return $db;
        }
    }
    
    function get_post_v1($db, $id) {
        return $db->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
    }
    get_post_v1(db(), 1024); //调用函数时注入依赖
    
    function get_post_v2($id) {
        $db = db(); //在函数内部包含依赖(耦合?不见得)
        return $db->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
    }
    get_post_v2(1024);
    
    $app['db'] = db(); //应用全局数组,Windows系统里的注册表?你的应用比Windows还复杂?
    function get_post_v3($id) {
        global $app; //全局变量
        return $app['db']->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
    }
    get_post_v3(1024);
    2022-11-14 19:08 回答
  • 解耦、方便unit test,显式注入的比较方便管理、最蛋疼的是隐式注入、半天找不到源文件。 laravel的DI其实也就是Requests和services了。

    2022-11-14 19:08 回答
  • 我对DI的观点一向是,与其说依赖注入,不如说是依赖管理,其实有些类似于composer、pip、maven这种更高一层管理应用与库之间的依赖工具,DI框架会带来这些好处(前提是好的DI框架):

    1. 通过配置改变依赖接口的实现,这也是DI功能最基本和最核心的功能

    2. 灵活控制依赖实现的实例范围,单例、每个线程一个、每个请求一个等等

    3. 依赖的参数,依赖的依赖等管理

    4. 代码更加简洁、逻辑更加清楚

    5. Mock方便测试方便,这个有了1就好办

    总的来说就是把应用中的功能块与功能块之间,类与类之间的依赖关系通过一个统一的框架集中管理起来。

    2022-11-14 19:08 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有