$ GLOBALS和依赖注入的替代方案?

时间:2014-10-02 03:49:39

标签: php standards

我正在开发的其中一个项目使用第三方库。目前,我将这些对象存储在全局变量中(例如$GLOBALS['_HTMLPurifier'])。

我知道每个人都说“不要在面向对象的代码中使用$GLOBALS,使用依赖注入”。问题是,这些类中的大多数都是为开发人员简化的。例如:

<?php

namespace Sarciszewski\MyProject\Security;

$GLOBALS['_HTMLPurifier'] = new \HTMLPurifier(
    \HTMLPurifier_Config::createDefault()
);

class XSS
{
    /* blah */

    public static function clean($input, $context)
    {
        /* logic here */
            $input = $_GLOBALS['_HTMLPurifier']->purify($input);
        /* other things here depending on $context */
    }
}

这个想法是,任何使用这个项目的人都需要这样做:

<?php
namespace \Otherdev\HelloWorld;
use \Sarciszewski\MyProject as MyP;

$x = isset($_GET['url']) ? $_GET['url'] : '';
echo "<input type=\"text\" name=\"url\" value=\"".MyP\Security\XSS::clean($x, 'attribute')."\" />";

我不想强迫别人注入依赖项。我宁愿保留这些对象的一个​​全局实例。单身人士在这里合适吗?或者是否应该遵循另一种设计模式?

(最糟糕的情况:我只是说它是这样做的,因为它完成了工作。)

要澄清:我没有建立一个其他人可能在他们的框架中使用的库,我正在建立一个调用其他人的库的框架。

我希望在“少写更多”方法中明确隐藏除单元测试作者之外的所有依赖注入。用户永远不必将对象传递给任何东西。

可用性比正确性更重要(这仍然很重要,但不是很重要)。另外,我想最小化其他第三方依赖项。 PHPUnit,HTMLPurifier和Twig都是我真正使用的。

我正在评估:

  • 单身
  • 全球变量

我不会评估的内容:

  • 依赖注入

欢迎任何第四种选择。

2 个答案:

答案 0 :(得分:3)

你误解了OOP的含义。

您花在代码上的大部分时间都不会继续编写代码。花在代码库上的绝大部分时间用于维护它,使其正常工作。 OOP,测试,编码风格等都是减少维护时间的工具,可以减少您需要完成的大部分工作。

OOP不是为了“简化”事物,相反,OOP通常比函数式编程更难阅读和理解。 OOP的目的是允许轻松重构层,而不必影响应用程序的其余部分。

我们可以争论为什么全局变量整天都不好。但在底线,全球空间是一个很好的漏洞来源。依赖注入是一个很好的替代方案。

对于您的具体示例,传递HTML纯化库听起来是个好主意。如果明天你会找到一个更好的库,你可以使用它提供更好的功能或性能,你可以通过使用依赖注入相对容易地切换。

答案 1 :(得分:0)

我不会尝试和自制一个好的DI解决方案,而是使用已经存在的库。

PHP DI非常好,因为它允许您只需在__construct方法中输入要注入另一个类的提示,它将自动包含在内!

这似乎不是一个答案,但问题是基于意见。我个人会说使​​用全局变量是一个非常糟糕的主意,因为它令人困惑,并且可能会引入一些非常难以跟踪代码中的错误。我会100%建议使用非常简单的DI来处理这种情况。

在您的情况下(使用PHP-DI),您可以执行以下操作:

class XSS
{
    /**
     * @Inject
     * @var HTMLPurifier
     */
    public static $purifier;

    public static function clean($input, $context)
    {
        /* logic here */
            $input = self::$purifier->purify($input);
        /* other things here depending on $context */
    }
}