Быстрый переход:
Я пишу это с целью лучшего понимания инъекций зависимостей и контейнеров IoC, но также, чтобы впоследствии я мог исправить ошибки в нем и использовать его, чтобы помочь обучить немного моих друзей о них.
На данный момент я пробовал прочитать документацию для различных фреймворков (laravel, fuel, codeigniter, symfony), и я обнаружил, что существует слишком много различных аспектов рамок, которые мне нужно было чувствовать удобными, используя это, что я решил попробовать просто изучите каждую из основных частей самостоятельно самостоятельно, прежде чем пытаться использовать их в самих рамках.
Я потратил несколько часов на поиски различных значений, просматривая ответы stackoverflow и читаю различные статьи, пытаясь понять, что такое IoC и как использовать его для правильного управления зависимостями, и я считаю, что понимаю, что это такое в концепции, но я все еще серый о том, как правильно его реализовать. Я думаю, что лучший способ для любого, кто читает это, чтобы помочь мне, – это дать то, что мое нынешнее понимание контейнеров IoC и инъекции зависимостей, а затем позволить людям, которые лучше понимают, чем я, указывают на то, что мое понимание не оправдалось.
Мое понимание:
Поэтому на этом этапе я начинаю пытаться использовать контейнер IoC для более сложных сценариев. На данный момент кажется, что для использования контейнера IoC я ограничен отношением has-a для почти любого класса, который я хочу создать, который имеет зависимости, которые он хочет определить в контейнере IoC. Что делать, если я хочу создать класс, который наследует класс, но только если родительский класс был создан определенным образом, он был зарегистрирован в контейнере IoC.
Например, я хочу создать дочерний класс mysqli, но я хочу зарегистрировать этот класс в контейнере IoC только для создания экземпляра родительского класса, сконструированного таким образом, который я ранее зарегистрировал в контейнере IoC. Я не могу придумать способ сделать это без дублирования кода (и поскольку это учебный проект, я стараюсь, чтобы он был «чистым», насколько это возможно). Вот еще несколько примеров того, что я пытаюсь описать.
Вот некоторые из моих вопросов:
Я знаю, что это очень долго, и просто хотел заранее поблагодарить любого, кто нашел время, чтобы прочитать его, и тем более, чтобы кто-то делился своими знаниями.
Проще говоря (потому что это не проблема, ограниченная только для мира ООП), зависимость – это ситуация, когда компонент А нуждается (зависит от) компонента В, чтобы делать вещи, которые он должен делать. Это слово также используется для описания зависимого компонента в этом сценарии. Чтобы поместить это в ООП / PHP, рассмотрите следующий пример с обязательной аналогией автомобилей:
class Car { public function start() { $engine = new Engine(); $engine->vroom(); } }
Car
зависит от Engine
. Engine
– зависимость от автомобиля . Этот фрагмент кода довольно плох, потому что:
Engine
MockEngine
для целей тестирования или TurboEngine
который расширяет исходный, без изменения Car
. Включение зависимостей – это способ решения всех этих проблем, поскольку тот факт, что Car
нуждается в Engine
и явно предоставляет ему один:
class Car { protected $engine; public function __construct(Engine $engine) { $this->engine = $engine; } public function start() { $this->engine->vroom(); } } $engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine $car = new Car($engine);
Вышеприведенный пример инсталляции конструктора , в котором зависимость (объект, зависящий от объекта) предоставляется зависимому (потребителю) через конструктор класса. Другой способ – разоблачить метод setEngine
в классе Car
и использовать его для ввода экземпляра Engine
. Это известно как инъекция сеттера и полезно в основном для зависимостей, которые должны быть заменены во время выполнения.
Любой нетривиальный проект состоит из кучи взаимозависимых компонентов, и становится легко потерять следы от того, что вводится там довольно быстро. Контейнер инъекции зависимостей – это объект, который знает, как создавать и настраивать другие объекты, знает, какова их связь с другими объектами в проекте, и делает инъекцию зависимостей для вас. Это позволяет централизовать управление всеми зависимостями вашего проекта (inter) и, что более важно, позволяет изменять / издеваться над одним или несколькими из них без необходимости редактировать кучу мест в вашем коде.
Давайте сравним аналогию с автомобилем и посмотрим, какие попытки OP пытаются достичь в качестве примера. Допустим, у нас есть объект Database
зависимости от объекта mysqli
. Предположим, мы хотим использовать действительно примитивный класс контейнера индексов индексов зависимости DIC
который предоставляет два метода: register($name, $callback)
чтобы зарегистрировать способ создания объекта под заданным именем и resolve($name)
чтобы получить объект из это имя. Наша настройка контейнера будет выглядеть примерно так:
$dic = new DIC(); $dic->register('mysqli', function() { return new mysqli('somehost','username','password'); }); $dic->register('database', function() use($dic) { return new Database($dic->resolve('mysqli')); });
Обратите внимание, что мы говорим нашему контейнеру, чтобы получить экземпляр mysqli
от себя, чтобы собрать экземпляр Database
. Затем, чтобы получить экземпляр Database
с автоматически зависящей зависимостью, мы просто:
$database = $dic->resolve('database');
В этом суть. Несколько более сложным, но все же относительно простым и легким для понимания контейнера PHP DI / IoC является Pimple . Проверьте его документацию для получения дополнительных примеров.
Что касается кода и вопросов OP:
mysqliWrapper
расширил mysql
или зависел от него. mysqliWrapper
IoC
из mysqliWrapper
вы mysqliWrapper
одну зависимость для другой. Ваши объекты не должны знать или использовать контейнер; в противном случае это не DIC, это шаблон Service Locator (анти). require
файл класса, прежде чем регистрировать его в контейнере, так как вы не знаете, собираетесь ли вы вообще использовать объект этого класса. Сделайте все настройки вашего контейнера в одном месте. Если вы не используете автозагрузчик, вы можете require
внутри анонимной функции, которую вы регистрируете в контейнере. Дополнительные ресурсы: