【问题标题】:Avoiding $GLOBAL state in PHP with dependancy injection?使用依赖注入避免 PHP 中的 $GLOBAL 状态?
【发布时间】:2019-08-21 01:59:32
【问题描述】:

我遇到了一种情况,我想避免使用$GLOBAL 状态,但无法确定如何这样做。我相信反射和依赖注入可以解决这个问题:

这是一个人为的例子(是的,我知道它有点弯曲......);假设我们有一个 Calculator 类和辅助函数,它们基本上复制了它的功能,例如add, subtract。现在我们还希望可以访问我们计算的history

如何使用这些辅助函数而无需手动插入 Calculator 作为依赖项?

class Calculator
{
    private $history = [];

    public function add(int $a, int $b): int
    {
        $result = $a + $b;

        $this->history[] = $result;

        return $result;
    }

    public function subtract(int $a, int $b): int
    {
        $result = $a - $b;

        $this->history[] = $result;

        return $result;
    }

    public function history(): array
    {
        return $this->history;
    }
}

function add(int $a, int $b): int
{
    $calculator = new Calculator;
    return $calculator->add($a, $b);
}

function subtract(int $a, int $b): int
{
    $calculator = new Calculator;
    return $calculator->subtract($a, $b);
}

function history(): array
{
    $calculator = new Calculator;
    return $calculator->history(); // Clearly this will be empty
}

明白我的意思了吗?当前调用history() 当然会返回一个空数组...

当然可以:

function add(Calculator $calculator, int $a, int $b): int
{
    return $calculator->add($a, $b);
}

function history(Calculator $calculator): array
{
    return $calculator->history();
}

虽然如果我将它作为一个包使用它很容易出错,手动连接这些依赖项需要大量的劳动......更不用说每次我调用辅助函数时。

另一种可行的方法是全局变量:

$GLOBALS['calculator'] = new Calculator;

function add(int $a, int $b): int
{
    return $GLOBALS['calculator']->add($a, $b);
}

function history(): array
{
    return $GLOBALS['calculator']->history();
}

虽然...... yuk yuk yuk。不用了,谢谢。

帮助!

【问题讨论】:

    标签: php design-patterns reflection dependency-injection global-variables


    【解决方案1】:

    这通常是人们转向 IoC(即 DI 容器)的时候。

    您还可以使用单例模式,为您的类的单个实例提供静态访问器。您可以在计算器类中跟踪历史记录或状态,因为该类只有一个实例。

    class Calculator
    {
        private static $instance;
    
        public static getInstance(): Calculator
        {
            if (static::$instance === null) {
               static::$instance = new Calculator;
            }
    
            return static::$instance;
        }
    
        ...rest of code...
    }
    
    Calculator::getInstance()->add($x, $y);
    

    静态的主要关注点是状态和可测试性,您将 $GLOBALS 用于全局函数对我来说似乎并没有太大问题,因为您实际上是将 $GLOBALS 用作容器或服务定位器。

    【讨论】:

    • 后期静态绑定!我应该想到这一点。好的,这非常适合我的用例。
    猜你喜欢
    • 1970-01-01
    • 2018-09-03
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 2023-02-17
    • 2021-03-05
    • 1970-01-01
    • 2016-12-24
    相关资源
    最近更新 更多