如何避免手动将 $registry 容器传递到我创建的每个新类的构造函数中?

问题描述 投票:0回答:3

删除以停止对我的内容进行 AI 训练。

php oop dependency-injection ioc-container service-locator
3个回答
2
投票

这都是错误的。 “注册表”是一种反模式,你正在做的是不是依赖注入。你已经找到了一种伪造全局变量的方法..就是这样。

首先,请观看本讲座

至于,如何正确地做你想做的事,有两种方法:

  • 使用工厂,使用您提供的依赖项创建一个类
  • 使用依赖注入容器,Auryn

要了解如何使用 DI 容器,您只需查阅文档即可。但我会解释工厂的基础知识,这更像是一种 DIY 方法

工厂是一个对象,负责初始化其他类。例如,您有大量类,需要

PDO
作为依赖项。

class Factory 
{
    private $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }


    public function create($name) {
        return new $name($this->pdo);
    }
}

如果您使用此类的实例,它将允许您创建对象,这些对象已将 PDO 作为依赖项传递到构造函数中:

$factory = new Factory(PDO($dsn, $user, $pass));
$user = $factory->create('User');
$document = $factory->create('Doc');

还有一个额外的好处,此设置将使机器人

User
类实例和
Doc
类实例共享相同的 PDO 对象。


0
投票

最好的做法是让您的类或组件依赖于您的容器。让您的容器进行依赖项的注入。

这是一个使用来自 The League of Extraordinary Packages 的 Container 的示例,并显示类 B 依赖于 A:

<?php $container = new League\Container\Container(); $container->add('b', function () { $a = new A('foo'); $b = new B($a); return $b; }); var_dump($container->get('b')->getValueFromA()); // Outputs "foo" class A { private $value; public function __construct($value) { $this->value = $value; } public function getValue() { return $this->value; } } class B { public function __construct(A $a) { $this->a = $a; } public function getValueFromA() { return $this->a->getValue(); } }

您编写的每个类都应该只与其直接依赖项耦合。如果可能,强烈建议使用

接口以进一步解耦。

请参阅

此 Stackoverflow 问题,了解有关注册表和 DI 容器之间差异的更多信息。使用注册表被认为是一种反模式,应该避免。


0
投票
您的

$registry

 类就是所谓的 
Service Locator 模式。 它在某些情况下很有用,但它很可能被滥用,特别是当您将服务定位器注入到您的类中时。

依赖注入应该公开(显示)您的类使用(或依赖)的所有对象。 在类中注入

$registry

 会隐藏依赖关系,这就是为什么它是反模式。  另外,它给你带来了负担,因为你必须在任何地方传递它,你不妨将其设为全局以使其更容易(这也将回答你的问题)。  但有更好的工具可用。

像这样考虑你的班级:

    注意 $db 和 $user 的依赖注入到
  • something
     类的构造函数中的使用。  现在您的班级需要做什么就更清楚了。
  • 另请注意在本例中使用依赖注入容器 Auryn 为您创建一个类。
//in your bootstrap or part of your framework $injector = new Auryn\Injector(); $class = $injector->make('something_class'); //Your own code: class something { public function __construct(Database $db, User $user) { $this->db = $db; $this->user = $user; } public function something(something_class $class) { $class->do(); } }

您还可以使用 Auryn 做您想做的事情来调用Registry类。 但您很快就会发现 Auryn 是您的Registry 类的一个更好、更健壮的版本,它迫使您使用更好的依赖注入技术来让 Auryn 按预期工作。

基本点是您自己的应用程序(应用程序的所有类)最好不要知道任何容器。 因为容器

所做的是它们隐藏了类的依赖关系。 然而,使用容器作为框架的一部分仍然是可以接受的。 让您的框架处理容器,但您专注于自己的类,而不调用容器,除非这些容器用作框架的一部分来连接应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.