Контейнер, буквально, – это то, что содержит вещи. Общие переменные, атрибуты объектов и т.д. Могут рассматриваться как контейнеры. То, что может вместить контейнер, полностью зависит от вашего определения контейнера. Конечно, есть такой контейнер, в котором хранится не текст, числовое значение, а объект, описание объекта (класс, интерфейс) или предоставление обратных вызовов объектов. С помощью этого контейнера мы можем реализовать множество расширенных функций. Наиболее часто упоминаются “развязка” и “Внедрение зависимостей (DI)”. Эта статья начинается отсюда.
Контейнер IoC, ядро laravel
Ядро Laravel-это одно Контейнер IoC
Согласно документу, назовите его” Сервисный контейнер
Как следует из названия, контейнер предоставляет ряд услуг, необходимых во всей структуре. Как новичок, многие люди столкнутся с трудностями в этой концепции. Поэтому я намерен начать с некоторого базового содержания. Понимая создание и решение зависимостей в объектно-ориентированной разработке, я постепенно приоткрою завесу “внедрения зависимостей” и постепенно пойму эту волшебную концепцию дизайна.
Большая часть содержания этой статьи предназначена для того, чтобы дать читателям пример, чтобы понять, что такое IoC (Инверсия контроля) и DI (Внедрение зависимостей). Понимая эти концепции, мы можем углубить наше понимание. Для получения дополнительной информации об использовании служебных контейнеров laravel ознакомьтесь с документацией.
История рождения контейнеров МоК
Есть много статей о контейнерах IoC, которые я писал раньше. Но теперь я собираюсь использовать вдохновение момента, чтобы начать все сначала, так что давайте начнем.
Супермен и сверхдержава, порождение зависимости!
Объектно-ориентированное программирование, постоянно контактируют следующие вещи: Интерфейс
、 класс
Также объект
。 Среди них интерфейс является прототипом класса, и класс должен следовать интерфейсу, который он реализует; объект является продуктом создания экземпляра класса, который мы называем экземпляром. Конечно, это, безусловно, не способствует пониманию, мы на самом деле напишем пункты в бесполезном обучении с помощью кода.
Миру монстров всегда нужны супергерои, чтобы уравновесить его.
Мы рассматриваем супермена как класс.
class Superman {}
Мы можем себе представить, что супермен должен был обладать по крайней мере одной сверхспособностью, когда он родился. Эта сверхдержава также может быть абстрагирована в объект. Определите класс для этого объекта, чтобы описать его. Для сверхдержавы должно быть много атрибутов и методов, которые мы можем себе представить в полной мере, но в настоящее время мы примерно определяем “сверхдержаву” только с атрибутами. Что касается того, что мы можем сделать, мы обогатим его позже:
class Power { /** * Capability value */ protected $ability; /** * Capability range or distance */ protected $range; public function __construct($ability, $range) { $this->ability = $ability; $this->range = $range; } }
Теперь давайте вернемся и изменим предыдущий класс Супермена, чтобы можно было создать Супермена со сверхдержавой:
class Superman { protected $power; public function __construct() { $this->power = new Power(999, 100); } }
Таким образом, когда мы создаем экземпляр Супермена, мы также создаем экземпляр Супермена, но мы видим, что между Суперменом и Сверхдержавой неизбежно существует зависимость.
Так называемая “зависимость” означает “если я завишу от тебя, я не смогу тебя бросить”.
В проекте, реализующем объектно-ориентированное программирование, такие зависимости можно увидеть повсюду. Небольшое количество зависимости не окажет слишком интуитивного влияния, мы постепенно распространяемся на этом примере, чтобы вы постепенно осознали, когда зависимость достигает такой величины, насколько кошмарный опыт. Конечно, я, естественно, расскажу о том, как решить эту проблему.
Куча путаницы – ужасная зависимость
В предыдущем примере класс сверхспособностей-это конкретная сверхспособность после создания экземпляра, но мы знаем, что сверхспособности сверхчеловека разнообразны, каждый метод сверхспособностей, атрибуты не являются небольшими различиями, не могут быть полностью описаны одним видом. Теперь мы собираемся изменить его. Давайте предположим, что Супермен может обладать следующими видами сверхспособностей:
- Полет, атрибуты: скорость полета, продолжительность полета
- Грубая сила, атрибуты: значение силы
- Энергетическая бомба, Атрибуты: Величина урона, Дальность стрельбы, Количество выстрелов одновременно
Мы создали следующие классы:
class Flight { protected $speed; protected $holdtime; public function __construct($speed, $holdtime) {} } class Force { protected $force; public function __construct($force) {} } class Shot { protected $atk; protected $range; protected $limit; public function __construct($atk, $range, $limit) {} }
* Для простоты я выписал не все конструкторы _construct (), а только параметры, которые необходимо передать.
Ладно, теперь наш Супермен немного занят. Когда Супермен инициализируется, создаем ли мы сверхспособности по мере необходимости, примерно следующим образом:
class Superman { protected $power; public function __construct() { $this->power = new Fight(9, 100); // $this->power = new Force(45); // $this->power = new Shot(99, 50, 2); /* $this->power = array( new Force(45), new Shot(99, 50, 2) ); */ } }
Нам нужно создать экземпляр ряда необходимых классов вручную в конструкторах (или других методах), что нехорошо. Как вы можете себе представить, если спрос изменится (разные монстры путешествуют по планете), потребуются более целенаправленные потребности. Новая Сверхдержава, или нужно изменить Подход Сверхдержавы, мы должны Перестроить
Супермена. Другими словами, меняя сверхспособности, я должен снова стать суперменом. 。 Это слишком неэффективно! Мир был разрушен еще до того, как его создал Новый Супермен.
В этот момент человек с быстрой идеей подумал: Почему нет? Способности Супермена могут быть заменены в любое время, просто добавив или обновив чип или другое устройство (вспомните Железного Человека). В таком случае не начинайте все сначала.
Да, именно так.
Мы не должны вручную закреплять его поведение “сверхчеловеческой” инициализации в классе “сверхчеловек”, а вместо этого отвечать за внешнее создание сверхчеловеческих модулей, устройств или чипов (позже совместно называемых “модулями”) и внедрять определенный интерфейс в тело сверхчеловека. Этот интерфейс устанавливается до тех пор, пока он является внешним. Это “модульное” устройство, соответствующее этому интерфейсу, может быть использовано Суперменом, что может усилить и увеличить одну из способностей Супермена. Мы можем назвать такое поведение внешней ответственностью за его зависимость от спроса.” Инверсия управления (IoC)
“。
Заводской режим, полагаясь на передачу!
Конечно, существует несколько способов добиться инверсии управления. А перед этим давайте узнаем кое-что интересное.
Мы можем представить, что компоненты, инструменты (или сверхчеловеческие модули) – это своего рода вещи, которые можно производить. Местом производства, конечно же, является “Фабрика”. Поэтому некоторые люди выдвигают такую модель: Заводская модель
。
Фабричный шаблон, как следует из его названия, является экземпляром внешней вещи, от которой зависит класс, шаблон разработки, который может быть создан одной или несколькими “фабриками”.” Фабричная модель
“。
Чтобы создавать сверхчеловеческие супермодули, мы создали фабрику, которая может производить все виды модулей одним способом:
class SuperModuleFactory { public function makeModule($moduleName, $options) { switch ($moduleName) { case 'Fight': return new Fight($options[0], $options[1]); case 'Force': return new Force($options[0]); case 'Shot': return new Shot($options[0], $options[1], $options[2]); } } }
В это время Супермен может использовать эту фабрику в начале ее создания!
class Superman { protected $power; public function __construct() { // Initialization Factory $factory = new SuperModuleFactory; // Manufacture the required modules by the method provided by the factory $this->power = $factory->makeModule('Fight', [9, 100]); // $this->power = $factory->makeModule('Force', [45]); // $this->power = $factory->makeModule('Shot', [99, 50, 2]); /* $this->power = array( $factory->makeModule('Force', [45]), $factory->makeModule('Shot', [99, 50, 2]) ); */ } }
Как вы можете видеть, нам больше не нужно инициализировать множество сторонних классов в начале сверхчеловеческой инициализации, просто инициализируйте заводской класс в соответствии с требованиями. Но, похоже, это не сильно отличается от того, что было раньше, просто не так сильно. новое
Ключевое слово. На самом деле, если мы немного изменим эту категорию, вы поймете истинное значение и ценность заводского класса.
class Superman { protected $power; public function __construct(array $modules) { // Initialization Factory $factory = new SuperModuleFactory; // Manufacture the required modules by the method provided by the factory foreach ($modules as $moduleName => $moduleOptions) { $this->power[] = $factory->makeModule($moduleName, $moduleOptions); } } } // Creating Superman $superman = new Superman([ 'Fight' => [9, 100], 'Shot' => [99, 50, 2] ]);
Результаты пересмотра являются удовлетворительными. В настоящее время создание Супермена больше не зависит от какого-либо класса суперспособностей. Если мы изменим или добавим новую суперспособность, нам нужно будет только изменить ее. Фабрика супер модулей
Все в порядке. Расширение Супердержавы без необходимости повторного редактирования файлов классов Супермена облегчает нам задачу. Но это только начало.
Дальше! Инъекция зависимостей, важный компонент контейнера IoC!
От зависимости Супермена от Сверхдержавы до зависимости Супермена от Фабрики модулей Сверхдержавы, работа с маленькими монстрами становится более удобной. Но, как вы можете видеть, зависимость не была освобождена, просто от первоначальной зависимости от множества внешних по отношению к “фабричной” зависимости. Если что-то пойдет не так на заводе, проблема станет очень сложной.
На самом деле, в большинстве случаев достаточно заводской модели. Недостатком заводского режима является то, что интерфейс неизвестен (то есть нет хорошей контрактной модели, которую я вкратце объясню), а тип объекта один. Короче говоря, он все еще недостаточно гибок. Тем не менее, заводская модель по-прежнему превосходна и подходит для большинства случаев. Но ради объяснения последнего Инъекции зависимостей
Давайте преувеличим недостатки заводской модели.
Мы знаем, что Супермен зависит от модулей, нам нужен единый интерфейс, чтобы стыковаться с интерфейсом впрыска на Супермене и, в конечном счете, сыграть определенную роль в усилении сверхдержавы.
На самом деле, я лгал раньше, не только кучке маленьких монстров, но и более крупным монстрам. Эй. Ну, на данный момент кажется, что производительность фабрики несколько недостаточна — поскольку все модули были расположены в заводском классе в соответствии с заводской моделью, если добавляются новые и расширенные модули, мы должны изменить заводской класс (например, добавить новые производственные линии).:
class SuperModuleFactory { public function makeModule($moduleName, $options) { switch ($moduleName) { case 'Fight': return new Fight($options[0], $options[1]); case 'Force': return new Force($options[0]); case 'Shot': return new Shot($options[0], $options[1], $options[2]); // case 'more': ....... // case 'and more': ....... // case 'and more': ....... // case 'oh no! its too many!': ....... } } }
Видеть… Кошмарное чувство!
На самом деле, вдохновения не хватает на один шаг! Вы можете придумать более гибкие способы! Да, следующий шаг-это наша главная вспомогательная роль сегодня, DI (внедрение зависимостей).
Из-за растущего спроса на супермодули нам необходимо объединить бизнесменов с высоким интеллектом в мире для совместного решения проблем, а не только нескольких фабричных монополий. Однако интеллектуалы с высоким IQ очень тщеславны и думают, что их идеи верны. Созданные мощные модули не имеют единого интерфейса и, естественно, не могут использоваться нормально. На этом этапе нам нужно предложить контракт, чтобы независимо от того, кто создал модуль, он соответствовал такому интерфейсу и, естественно, мог использоваться нормально.
interface SuperModuleInterface { /** * Supercapacity activation method * * Any superpower must have this method and a parameter. *@ Param array $target is targeted and can be one or more, oneself or others */ public function activate(array $target); }
Выше мы определили интерфейс (спецификацию, контракт на модули сверхспособностей), которому должны соответствовать все созданные модули, прежде чем их можно будет изготовить.
На самом деле, это в PHP Интерфейс
Использование и значение! Многие люди думают, зачем PHP нужен интерфейс такого рода вещей? Разве это не на таких языках, как java, C #? Таким образом, пока это обычный объектно-ориентированный язык программирования (хотя PHP может быть ориентирован на процессы), он должен обладать этой функцией. Из-за одного Объекта
Это его шаблон или прототип.– Класс
Иногда, когда реализован единый подход и реализованы разные функции (или функции), классов будет много. В настоящее время необходим контракт, позволяющий вам писать интерфейсы, которые могут быть заменены в любое время, но не окажут влияния. Такого рода жесткая спецификация, предложенная самим языком программирования, добавит больше отличных функций.
Хотя есть некоторые повороты и повороты, в нашем следующем примере вы постепенно поймете преимущества интерфейса.
В настоящее время те таланты с высоким IQ, которые предлагают лучшие модули сверхспособностей, следуют этому интерфейсу и создают следующие классы (модули):
/** * X-superenergy */ class XPower implements SuperModuleInterface { public function activate(array $target) { // This is just an example. Specific self-Brain tonic } } /** * Ultimate bomb (just so vulgar) */ class UltraBomb implements SuperModuleInterface { public function activate(array $target) { // This is just an example. Specific self-Brain tonic } }
В то же время, чтобы некоторые “каменщики” не действовали умно, или некоторые предатели злонамеренно обманывали, не соблюдали контракт на случайное создание модулей, влияющих на Супермена, мы реформируем метод инициализации Супермена:
class Superman { protected $module; public function __construct(SuperModuleInterface $module) { $this->module = $module } }
Ремонт закончен! Теперь, когда мы инициализируем класс Superman, предоставленный экземпляр модуля должен быть одним Интерфейсом супер модуля
Реализацией интерфейса. В противном случае будет выведено сообщение об ошибке.
Именно потому, что создание Супермена становится проще, Супермену не нужно слишком много сверхспособностей. Мы можем создать более одного Супермена и отдельно внедрить в него необходимые модули с супермощностью. Таким образом, хотя у Супермена есть только одна сверхдержава, но Супермену легче стать большим, мы не боимся монстров!
Теперь некоторые люди задаются вопросом, что вы хотите сказать? Инъекция зависимостей
Как насчет этого?
На самом деле, вышесказанное касается внедрения зависимостей.
Что называется Инъекцией зависимостей
?
Эта статья начинается с серии зависимостей, упомянутых до сих пор, до тех пор, пока они не создаются внутренне (например, инициализация, конструкторы) __construct
В заводском методе, вручную новый), но по внешним параметрам или другим формам внедрения принадлежат Инъекции зависимостей (DI)
. Был ли это взрыв бодрости? На самом деле, все так просто. Вот типичная инъекция зависимостей:
// Super Capability Module $superModule = new XPower; // Initialize a superman and inject a super module dependency $superMan = new Superman($superModule);
В этой статье так много нужно сказать об основной вспомогательной роли внедрения зависимостей. Понимание внедрения зависимостей позволяет нам пойти дальше. Медленно приближается сегодняшний главный герой…
Более продвинутый заводской контейнер IoC!
Просто перечислил фрагмент кода:
$superModule = new XPower; $superMan = new Superman($superModule);
Читатели должны видеть, что супермодуль создается вручную, супермен создается вручную, и только что созданный супермодуль вводится. Ха-ха, инструкция.
В современном обществе это должно быть эффективное производство, чистый цех и совершенная автоматическая сборка.
Пришла группа монстров. Нереально производить сверхчеловеческих существ так неэффективно. Нам нужна автоматизация – самое большее одна команда, тысячи солдат встречаются друг с другом. Нам нужен семинар высокого уровня. Нам нужно только отправить сценарий в мастерскую, чтобы фабрика могла автоматизировать производство с помощью инструкций. Эта более продвинутая фабрика является сублимацией заводской модели.– Контейнер IoC
。
class Container { protected $binds; protected $instances; public function bind($abstract, $concrete) { if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } public function make($abstract, $parameters = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } }
В это время родился очень грубый контейнер. Сейчас это действительно скромно, но это не мешает нам продвигать его дальше. Начните с настоящего и посмотрите, как работает контейнер.
// Create a container (later called a superfactory) $container = new Container; // Add Superman's production script to the superfactory $container->bind('superman', function($container, $moduleName) { return new Superman($container->make($moduleName)); }); // Production scripts for adding super modules to the superfactory $container->bind('xpower', function($container) { return new XPower; }); // Ibid. $container->bind('ultrabomb', function($container) { return new UltraBomb; }); // ******************************** Gorgeous Separation Line************************************************************** // Start production $superman_1 = $container->make('superman', ['xpower']); $superman_2 = $container->make('superman', ['ultrabomb']); $superman_3 = $container->make('superman', ['xpower']); //... Feel free to add
Видишь? В ходе начальных операций Привязки
мы зарегистрировали некоторые производственные сценарии на суперфабрике, которые будут выполнены, когда будут выпущены производственные инструкции. Вы нашли его? Мы полностью устранили зависимость между модулями Супермена и Сверхдержавы, и, что более важно, классы контейнеров вообще не зависели от них! Мы добавляем обратный вызов (который может быть анонимной функцией, неанонимной функцией, методом класса) в контейнер путем регистрации и привязки в качестве экземпляра создания класса. Скрипт Только в реальном мире Производство (создание)
Операция запускается, когда она вызывается для выполнения.
Такой подход упрощает создание экземпляра при устранении его зависимостей и делает его более гибким. Когда возникает новое требование, может быть привязан только один дополнительный “производственный сценарий”.
На самом деле, настоящие контейнеры IoC более продвинуты. В нашем текущем примере нам все еще нужно вручную указать параметры модуля, необходимые Супермену, но реальный контейнер IoC автоматически выполнит поиск соответствующих требований к зависимостям в куче зарегистрированных и связанных экземпляров и введет их в параметры конструктора в соответствии с требованиями к зависимостям класса. Это то, что делает сервисный контейнер Laravel framework. Реализация этой функции не является теоретической проблемой, но я не буду писать об этом в этой статье, потому что… Мне лень писать.
Но позвольте мне сказать вам, что этот автоматический поиск зависимых требований осуществляется с помощью Отражения
Реализованного, в самый раз, механизма отражения идеальной поддержки PHP! О рефлексии, официальные документы PHP содержат подробную информацию, а китайский перевод в основном освещен, достаточно для изучения и изучения!
http://php .net/руководство/ж/книга…
Теперь, до сих пор, мы больше не боимся монстров. Умные бизнесмены провели мозговой штурм и организовали создание нормативных модулей сверхспособностей в соответствии с интерфейсными контрактами. Супермен начал массовое производство. В конечном счете, каждый является Суперменом, и вы можете им быть. !
Вернитесь в нормальный мир. Мы начали заново изучать ядро laravel.
Теперь давайте медленно начнем понимать суть laravel. На самом деле, ядром laravel является контейнер IoC, который является усовершенствованным контейнером IoC, о котором я упоминал ранее.
Можно сказать, что ядро laravel само по себе очень легкое, и в нем нет волшебной и существенной прикладной функции. Многие люди используют различные функциональные модули, такие как Маршрут
、 Красноречивый ORM (компонент ORM базы данных)
、 Запрос и ответ
Подождите минуту и так далее. На самом деле, эти классы предоставляются независимыми от ядра модулями классов. Эти классы регистрируются, создаются и в конечном итоге используются вами. На самом деле, все они отвечают за сервисный контейнер laravel.
Мы самые распространенные. Маршрут
Класс в качестве примера. Вы часто можете видеть определения маршрутизации, подобные этому:
Route::get('/', function() { // bla bla bla... });
На самом деле, Маршрут
Классы определены в этом пространстве имен: Осветить\Маршрутизация\Маршрутизатор
Документация vendor/laravel/framework/src/Illuminate/Routing/Router.php
。
Открыв, мы обнаруживаем ряд методов такого рода, таких как get
, post
, любой
Ожидание не является статическим методом. В чем дело? Не волнуйся, давай продолжим.
Поставщик Услуг
В предыдущем разделе, посвященном контейнерам IoC, мы упоминали, что класс должен быть привязан и зарегистрирован в контейнере, прежде чем его можно будет “изготовить”.
Да, если класс должен быть извлечен контейнером, он должен быть сначала зарегистрирован в контейнере. Поскольку laravel называет этот контейнер служебным контейнером, нам нужна услуга. Сначала мы должны зарегистрироваться и привязать эту услугу к контейнеру. Итак, то, что предоставляет услугу и привязывает услугу к контейнеру, – это Поставщик услуг
.
Хотя привязка класса к контейнеру не обязательно должна проходить через Поставщика услуг
.
Однако мы знаем, что иногда нашим классам и модулям понадобятся другие классы и компоненты. Чтобы гарантировать, что необходимые модули и компоненты не будут зарегистрированы на этапе инициализации, laravel разделит поведение регистрации и инициализации. Когда мы регистрируемся, мы можем только зарегистрироваться. Когда мы инициализируем, это инициал. Изменить. Разделенный продукт-это то, чем он является сейчас. Поставщик услуг
。
Поставщики услуг в основном делятся на две части. Регистрация (регистрация)
и Загрузка (загрузка, инициализация)
Конкретные справочные документы. регистрация
Будьте ответственны за регистрацию “скриптов” в контейнерах, но будьте осторожны, чтобы реестр не полагался на неизвестные вещи. Если это так, перейдите в раздел загрузка
Часть.
Фасад
Давайте теперь ответим на предыдущий вопрос о Маршруте
Вопрос о том, почему к методам можно получить доступ статическим способом. На самом деле проблема задокументирована. Проще говоря, он имитирует класс и предоставляет статический магический метод. __вызов статический
И сопоставьте статический метод с реальным методом.
То, что мы используем Маршрут
Классы на самом деле Осветить\Поддержка\Фасады\Маршрут
принять class_alias()
Функциональное создание псевдоним
Просто этот класс определен в файле. vendor/laravel/framework/src/Illuminate/Support/Facades/Route.php
。
Давайте откроем файл и посмотрим… А? Почему существует только такой простой фрагмент кода?
На самом деле, если вы присмотритесь повнимательнее, вы обнаружите, что этот класс наследует класс под названием Фасад
Класс, тайна здесь почти решена.
В приведенном выше простом определении мы видим, что getFacadeAccessor
Метод возвращает маршрут
Что это значит? На самом деле значение Поставщик услуг
Зарегистрирован, вы должны знать, что зарегистрирован, конечно, реальный класс маршрутизации!
Кто – то спросит, как был достигнут фасад. Я не хочу быть слишком подробным. Одна из причин в том, что я ленив. Другая причина заключается в том, что я нахожу что-то более легкое для понимания и нелегкое для забвения. Я уже упоминал о многих деталях, и я предлагаю вам изучить их самостоятельно.
До сих пор мы уже говорили об этом.
Мир! Мы должны подвести итоги!
В любом случае, в мире царит мир.
Я хочу подвести здесь итог тому, что многие вещи не сложны, и чего я боюсь, так это сложного теоретического содержания. Я думаю, что именно это происходит, когда ты думаешь о многих вещах. Многие люди думают, что laravel нехорош, это нехорошо, здесь сложно, я могу только сказать, что laravel-это не первоклассный и отличный фреймворк, что laravel-это первоклассный, отличный фреймворк людей, а не фанатов laravel или следящих за тенденцией шумихи. Самая большая особенность и превосходство Laravel заключается в том, что он использует множество новых (не совсем новых) концепций и технологий PHP (куча грамматического сахара). Таким образом, laravel действительно вписывается в рамки обучения. Идея Laravel действительно сильно отличается от других фреймворков, что также требует людей, которые учатся владеть php, и Прочной основы
! Если вам очень трудно освоить фреймворк laravel, есть только одна причина: ваша основа PHP не очень хороша.
Кроме того, если вы хорошо умеете использовать пространства имен и объектно-ориентированные функции, чтобы что-то найти, вы обнаружите, что все это так просто.