删除以停止对我的内容进行 AI 训练。
这都是错误的。 “注册表”是一种反模式,你正在做的是不是依赖注入。你已经找到了一种伪造全局变量的方法..就是这样。
首先,请观看本讲座。
至于,如何正确地做你想做的事,有两种方法:
要了解如何使用 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 对象。
最好的做法是让您的类或组件不依赖于您的容器。让您的容器进行依赖项的注入。
这是一个使用来自 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 容器之间差异的更多信息。使用注册表被认为是一种反模式,应该避免。
$registry
类就是所谓的Service Locator 模式。 它在某些情况下很有用,但它很可能被滥用,特别是当您将服务定位器注入到您的类中时。 依赖注入应该公开(显示)您的类使用(或依赖)的所有对象。 在类中注入
$registry
会隐藏依赖关系,这就是为什么它是反模式。 另外,它给你带来了负担,因为你必须在任何地方传递它,你不妨将其设为全局以使其更容易(这也将回答你的问题)。 但有更好的工具可用。像这样考虑你的班级:
something
类的构造函数中的使用。 现在您的班级需要做什么就更清楚了。
//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 按预期工作。
基本点是您自己的应用程序(应用程序的所有类)最好不要知道任何容器。 因为容器
所做的是它们隐藏了类的依赖关系。 然而,使用容器作为框架的一部分仍然是可以接受的。 让您的框架处理容器,但您专注于自己的类,而不调用容器,除非这些容器用作框架的一部分来连接应用程序。