Я делал MVC уже несколько месяцев, и я храню все в своем $ реестра объект. Когда я создаю новый класс, я обычно только прохожу реестр, но мне приходится постоянно проходить $this->registry
при создании нового класса.
например
class something
{
public function __construct($registry)
{
$this->registry = registry;
$this->db = $registry->db;
$this->user = $registry->user; // ......
}
public function something()
{
$class = new something_class($this->registry);
$class->do();
}
}
class something_class
{
public function __construct($registry)
{
$this->registry = $registry;
}
public function do()
{
echo 'Doing something ....';
}
}
Мой вопрос заключается в том, как я могу как-то обработать передачу реестра в новый класс за кулисами (в данном случае при создании экземпляра что-то в классе) внутри класса реестра? Я абсолютно уверен, что есть простой способ сделать это, но я не могу найти ничего, связанного с тем, что я ищу.
Вот мой реестр учебный класс:
<?php
class registry
{
protected $vars = array();
public function &__set($index, $value)
{
$this->vars[$index] = $value;
return $value;
}
public function &__get($index)
{
return $this->vars[$index];
}
}
Это все неправильно. «Реестр» — это антипаттер, и то, что вы делаете, это не внедрение зависимости. Вы нашли способ подделать глобальные переменные … вот и все.
Для начала, пожалуйста, смотрите эта лекция.
Что касается того, как правильно делать то, что вы хотите, есть два способа:
Чтобы узнать, как вы используете 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.
Лучше всего иметь классы или компоненты не зависеть от вашего контейнера. Позвольте вашему контейнеру внедрить зависимости.
Вот пример, который использует Контейнер от Лиги Чрезвычайных Пакетов и показывает, что класс 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
класс это то, что называется Сервисный локатор шаблон. Это полезно в некоторых контекстах, но имеет большой потенциал для злоупотреблений, особенно когда вы вводите указатель службы в ваш класс.
Предполагается, что внедрение зависимостей предоставляет все объекты, которые ваш класс использует (или зависит). Инъекционное $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 работал по назначению.
Суть в том, что ваше собственное приложение (все классы вашего приложения) лучше не знать о каком-либо контейнере. Потому что какие контейнеры делать они скрывают зависимости от ваших классов. Однако остается приемлемым использовать контейнеры как часть каркаса. Позвольте вашей инфраструктуре обрабатывать контейнеры, но вы сосредоточитесь на своих собственных классах, не вызывая контейнеры, если эти контейнеры не используются как часть вашей инфраструктуры для подключения вашего приложения.