gpt4 book ai didi

php - 你能在使用依赖注入(inject)的同时避免大量的私有(private)变量吗?

转载 作者:可可西里 更新时间:2023-10-31 23:30:30 24 4
gpt4 key购买 nike

我一直在阅读/观看很多推荐 Material ,最近是这个 - MVC for advanced PHP developers .出现的一件事是单例是不好的,它们在类之间创建依赖关系,而依赖注入(inject)很好,因为它允许单元测试和解耦。

在我编写程序之前,一切都很好。我们以网店的产品页面为例。首先我有我的页面:

class Page {
public $html;

public function __construct() {

}

public function createPage() {
// do something to generate the page
}

public function showPage() {
echo $this->html;
}
}

到目前为止一切正常,但是页面需要一个产品,所以让我们传入一个:

class Page {
public $html;
private $product;

public function __construct(Product $product) {
$this->product = $product;
}

public function createPage() {
// do something to generate the page
}

public function showPage() {
echo $this->html;
}
}

我使用依赖注入(inject)来避免让我的页面类依赖于产品。但是,如果页面有多个公共(public)变量,并且在调试时我想查看其中的内容怎么办。没问题,我只是var_dump()页面实例。它给了我页面中的所有变量,包括产品对象,所以我也得到了产品中的所有变量。

但是 product 不仅具有包含实例化产品的所有详细信息的所有变量,它还具有获取这些产品详细信息的数据库连接。所以现在我的 var_dump()也有数据库对象。现在它开始变得有点长并且更难阅读,即使在 <pre> 中也是如此。标签。

产品也属于一个或多个类别。为了争论起见,我们假设它属于两类。它们在构造函数中加载并存储在包含数组的类变量中。所以现在我不仅拥有产品和数据库连接中的所有变量,而且还有类别类的两个实例。当然类别信息也必须从数据库中加载,所以每个类别实例也有一个数据库私有(private)变量。

所以现在当我 var_dump()我的页面 我有所有页面变量、所有产品变量、数组中类别变量的倍数以及数据库变量的 3 个副本(一个来自产品实例,一个来自每个类别实例)。我的输出现在很大而且难以阅读。

现在单例怎么样?让我们看看我使用单例的页面类。

class Page {
public $html;

public function __construct() {

}

public function createPage() {
$prodId = Url::getProdId();
$productInfo = Product::instance($prodId)->info();
// do something to generate the page
}

public function showPage() {
echo $this->html;
}
}

我也在 Product 类中使用类似的单例。现在当我var_dump()我的 Page 实例我只得到我想要的变量,那些属于页面的变量,没有别的。

但这当然会在我的类之间创建依赖关系。并且在单元测试中没有办法不调用产品类,这使得单元测试变得困难。

我怎样才能获得依赖注入(inject)的所有好处,同时仍然可以使用 var_dump() 轻松调试我的类? ?我怎样才能避免将所有这些实例存储为我的类中的变量?

最佳答案

我会尝试在这里写几件事。

关于var_dump():

我使用 Symfony2 作为默认框架,有时,var_dump() 是快速调试的最佳选择。但是,它可以输出如此多的信息,以至于您无法阅读所有内容,对吗?比如,转储 Symfony 的 AppKernel.php,或者更接近您的情况,一些具有 EntityManager 依赖项的服务。恕我直言,当您调试少量代码时,var_dump() 很不错,但是大型和复杂的产品会使 var_dump() 无效。我的替代方案是使用与您的 IDE 集成的“真正的”调试器。使用 PhpStorm 下的 xDebug,我不再需要 var_dump()

关于“为什么?”的有用链接和“如何做?”是here .

关于 DI 容器:

它的忠实粉丝。它很简单,使代码更稳定;它在现代应用程序中很常见。但我同意你的看法,背后有一个真正的问题:嵌套依赖。这是过度抽象,它通过添加有时不必要的层来增加复杂性。

Masking the pain by using a dependency injection container is making your application more complex.

如果您想从您的应用程序中删除 DIC,并且您确实可以做到,那么您根本就不需要 DIC。如果您想替代 DIC,那么...Singleton 被认为是不可测试代码和应用程​​序的巨大状态空间的不良做法。 服务定位器对我来说有no benefits at all .所以看起来唯一的方法就是学习正确使用 DI。

关于您的示例:

我立即看到一件事 - 通过 construct() 注入(inject)。这很酷,但我更喜欢可选的传递依赖关系而不是需要它的方法,例如通过服务 config.yml 中的 setter 。

class Page
{
public $html;

protected $em;
protected $product;

public function __construct(EntityManager $em) {
$this->em = $em;
}

//I suppose it's not from DB, because in this case EM handles this for you
protected function setProduct(Product $product)
{
$this->product = $product;
}

public function createPage()
{
//$this->product can be used here ONLY when you really need it

// do something to generate the page
}

public function showPage()
{
echo $this->html;
}
}

我认为当您在执行期间只需要一些对象时它提供了所需的灵 active ,并且在给定的时刻您可以在您的类中看到您只需要的属性。

结论

请原谅我宽泛而肤浅的回答。我真的认为您的问题没有直接答案,任何解决方案都将基于意见。我只是希望您可能会发现 DIC 确实是最好的解决方案,缺点有限,而且集成调试器而不是倾倒整个类(构造函数、服务等...)。

关于php - 你能在使用依赖注入(inject)的同时避免大量的私有(private)变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28574297/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com