Создаем свой Фреймворк на компонентах symfony2. Часть 12

В предыдущей статье цикла, мы убрали весь код из класса Framework, благодаря тому, что этот класс теперь наследуется от HttpKernel. И, раз уж, он пуст, возможно, вам захочется перенести сюда некоторый код из фронт-контроллера.

Сам фронт-контроллер стал куда более лаконичным:

Такая краткость дает нам возможность использовать более одного фронт-контроллера для приложения. Зачем? Ну например, что бы иметь различные конфигурации для разработки и production. В разработческом окружении вам может потребоваться отображение ошибок в браузере.

Но вряд ли вы захотите включить эту настройку на боевом серваке. В общем, два разных фронт-контроллера дают вам возможность немного варьировать конфигурацию приложения для разного окружения.

Однако, перенос кода из фронт-контроллера в класс фреймворка несет в себе несколько проблем:

  1. У нас больше нет возможности создавать своих слушателей, ведь объект EventDispatcher теперь не доступен вне фреймворка (Вообще эту проблему можно обойти, добавив метод Framework::getEventDispatcher()).
  2. Теперь мы не можем использовать свою реализацию UrlMatcher или ControllerResolver
  3. Исходя из предыдущего пункта, нам стало сложнее тестировать наш фреймворк, т.к. мы больше не можем заменить зависимости заглушками.
  4. Мы не можем изменить кодировку, которая передается в ResponseListener (Эту проблему можно было бы обойти, передавая кодировку параметром конструктора).

В нашем прошлом коде таких проблем не было, потому что мы использовали внедрение зависимостей. Все зависимости наших объектов передавались в их конструкторах (например диспетчер, благодаря чему мы имели полный контроль над его созданием и настройкой).

Значит ли это, что мы должны жертвовать гибкостью, кастомизацией и простотой тестирования ради возможности не копипастить кучу кода при добавлении нового фронт-контроллера? Конечно не значит! Решить эти и многие другие проблемы нам поможет Symfony2 dependency injection container.

Создайте новый файл для описания конфигурации контейнера:

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

Как видите, все объекты связанны именами — уникальными строками, которые идентифицируют каждый из них. Имена дают нам возможность получить объект и сослаться на него при определении другого объекта.

Осталось собрать все это во фронт-контроллере:

Так как созданием всех объектов теперь управляет контейнер внедрения зависимостей, код фреймворка снова стал предельно прост:

А так можно добавить нового слушателя во фронт-контроллер:

Контейнер можно конфигурировать с помощью параметров. Давайте добавим параметр, определяющий работаем ли мы в режиме отладки:

Эти параметры можно использовать при определении объектов. Сделаем возможность настраивать кодировку:

Теперь, перед тем как использовать этот объект, нужно задать параметр charset

Вместо того, что бы полагаться на соглашение о том, что маршруты находятся в переменной $routes, давайте зададим параметр:

И соответственно во фронт-контроллере:

Мы коснулись лишь малой части того, что можно делать, используя контейнер. Не обсудили передачу названий классов параметрами, переопределение имеющихся описаний объектов, представление контейнера в виде класса на чистом PHP и многое-многое другое.

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

К содержанию >>
Оригинал статьи на английском языке >>
Исходный код из статьи >>

Не забудьте поделиться статьей с друзьями

Подписывайтесь на меня в соц. сетях

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *