Intereting Posts
Как экспортировать массив PHP, где каждая пара ключей и значений находится в отдельной строке? PHP: использование пробелов в индексах ассоциативного массива Могу ли я предсказать, насколько большой будет мой индекс Zend Framework? (и некоторые быстрые Q: s) Ошибка HY093 с запросом MySQL PDO MySQL PHP – SELECT WHERE id = array ()? Результат странного вычитания с PHP медиа конвертация библиотека / плагин предпочтительно php Сценарий загрузки Joomla на определенной странице PHP glob () для отображения файла, который не начинается с подчеркивания? Что может вызвать прерывистый SQLSTATE Нет таких ошибок файла или каталога из php PDO mysql в Debian Lenny? Наличие цикла PHP-скрипта навсегда выполняющего задания на работу из очереди Parsing / edition docx файл с PHP Скопировать изображение с удаленного сервера через HTTPS Получать контент внутри HTML-тегов с помощью RegExp Использовать PHP для отображения результатов MySQL в таблице HTML

Как избежать вручную передать мой контейнер реестра $ в конструктор каждого нового класса, который я делаю?

Я занимаюсь 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 ....'; } } 

Мой вопрос: как я могу каким-то образом обработать передачу реестра в новый класс за кулисами (в этом случае при создании экземпляра something_class) в классе реестра? Я абсолютно уверен, что есть простой способ сделать это, но я не могу найти ничего связанного нигде с тем, что я ищу.

Вот мой класс реестра :

 <?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]; } } 

Это все неправильно. «Registry» – это анти-patter, и то, что вы делаете, не является инъекцией зависимости . Вы нашли способ подделать глобальные переменные .. вот и все.

В начале, пожалуйста, смотрите эту лекцию .

Что касается того, как правильно делать то, что вы хотите, есть два способа:

  • используйте фабрику, которая создает класс, используя зависимости, которые вы предоставили
  • использовать контейнер для инъекций зависимости, Аурин

Чтобы узнать, как вы используете контейнер 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.

Лучше всего, чтобы ваши классы или компоненты не зависели от вашего контейнера. Пусть ваш контейнер выполняет инъекции зависимостей.

Вот пример, который использует Container из The League of Extraordinary Packages и показывает, что класс 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 – это так называемый шаблон Locator . Это полезно в некоторых контекстах, но у него высокий потенциал для злоупотребления, особенно когда вы вводите локатор службы в свой класс.

Предполагается, что инъекция зависимостей должна показывать (показывать) все объекты, которые использует ваш класс (или зависит от них). Внедрение $registry в ваш класс вместо скрывает зависимости, и именно поэтому это анти-шаблон. Кроме того, это создает для вас бремя, так как вы должны передавать его повсюду, вы также можете сделать его глобальным, чтобы упростить (это также ответит на ваш вопрос). Но лучшие инструменты доступны.

Рассмотрим свой класс следующим образом:

  • Обратите внимание на использование вложения зависимостей $ db и $ user в конструктор класса. Теперь более понятно, что должен работать ваш класс.
  • Также обратите внимание на использование контейнера для инъекций зависимостей в этом случае 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 для выполнения того, что вы хотите сделать, чтобы вызвать класс реестра. Но вскоре вы обнаружите, что Auryn является более надежной версией вашего класса реестра, и это заставляет вас использовать лучшие методы инъекций зависимостей для Auryn для работы по назначению.

Основной момент заключается в том, что ваше собственное приложение (все классы вашего приложения) лучше не знать о каком-либо контейнере. Поскольку в каких контейнерах они скрывают зависимости от ваших классов. Однако остается приемлемым использование контейнеров в рамках структуры. Пусть ваша инфраструктура обрабатывает контейнеры, но вы фокусируетесь на своих собственных классах, не вызывая контейнеры, если эти контейнеры не используются как часть вашей структуры для подключения вашего приложения.