秒杀系列04 ~ 手撸IoC容器

接上文:秒杀系列03

先看看我们上文的代码

$db = new Db($dsn);
$user = new User($db);

上面的写法的问题:

如果有很多依赖需要注入,比如mysql实例,redis实例,mongo实例,那么每次使用业务类时,都要写一次各个依赖的实例化过程,还是很繁琐。

IoC 容器解决了什么问题:

提前处理依赖关系(配置,注解),隐藏注入过程。

即使用业务类时,不需要再去手动实例化一堆依赖,容器会自动管理依赖关系了。

更重要的是,在框架加载时,就可以提前初始化容器,后续就可以直接使用业务类了。

对于一些常驻内存框架,我们还可以复用容器中的依赖。

手写一个简单的 IoC 容器

test.php

<?php
class Dsn {
    private $dsn = "mysql:host=192.168.0.101;dbname=seckill;charset=utf8;user=seckill;password=BBHyiFWiXrpxji5S;";
    public function getdsn() {
        return $this->dsn;
    }
}

class Db {
    private $pdo;
    public function __construct($dsn) {
        try {
            $this->pdo = new PDO($dsn);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            echo "mysql连接失败:" . $e->getMessage();
        }
    }

    public function queryForRows($sql) {
        try {
            $stmt = $this->pdo->query($sql);
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            echo "查询失败:" . $e->getMessage();
        }
    }
}

class User {
    private $db;

    public function __construct(Db $Db)   // 这里直接注入Db的实例了
    {
        $this->db = $Db;  // 这里不在主动实例化Db了,直接用注入的Db实例
    }

    public function getAllUsers() : array {
        return $this->db->queryForRows("select * from users");
    }
}

class ClassFactory {
    private static $container = [];

    public static function set(string $key, callable $func) {
        self::$container[$key] = $func;
    }

    public static function get(string $key) {
        if (isset(self::$container[$key])) {
            return (self::$container[$key])(); // 执行匿名函数
        }
        return null;
    }
}

// User 依赖 Db,Db 依赖 Dsn
ClassFactory::set("Dsn", function () {
    return new Dsn();
});
ClassFactory::set("Db", function () {
    return new Db(ClassFactory::get("Dsn")->getdsn());
});
ClassFactory::set("User", function () {
    return new User(ClassFactory::get("Db"));
});

////////////////下面是业务处理/////////////////

$user = ClassFactory::get("User");
var_dump($user->getAllUsers());

上面是我们手写的依赖关系,更好的方式是借助于配置,自动装配,或者借助于 注解

使用第三方库,简单的实现IoC

安装 https://php-di.org/doc/getting-started.html

// 进入到项目根目录下,执行
composer require php-di/php-di

test.php 代码:

<?php
require_once __DIR__ . "/vendor/autoload.php";

class Dsn {
    private $dsn = "mysql:host=192.168.0.101;dbname=seckill;charset=utf8;user=seckill;password=BBHyiFWiXrpxji5S;";
    public function getdsn() {
        return $this->dsn;
    }
}

class Db {
    private $pdo;
    public function __construct($dsn) {
        try {
            $this->pdo = new PDO($dsn);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            echo "mysql连接失败:" . $e->getMessage();
        }
    }

    public function queryForRows($sql) {
        try {
            $stmt = $this->pdo->query($sql);
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            echo "查询失败:" . $e->getMessage();
        }
    }
}

class User {
    private $db;

    public function __construct(Db $Db)   // 这里直接注入Db的实例了
    {
        $this->db = $Db;  // 这里不在主动实例化Db了,直接用注入的Db实例
    }

    public function getAllUsers() : array {
        return $this->db->queryForRows("select * from users");
    }
}

$container = new DI\Container();
$container->set("Dsn", function () {
    return new Dsn();
});
$container->set("Db", function (\DI\Container $c) {  //  \DI\Container $c 基于反射去获取container对象
    return new Db($c->get("Dsn")->getdsn());
});
$container->set("User", function (\DI\Container $c) {
    return new User($c->get("Db"));
});

////////////////////////////////////////////

$user = $container->get("User");
var_dump($user->getAllUsers());

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇