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

Вы наверное думаете, что наш фреймворк уже достаточно хорош, и вы правы! Но, тем не менее, давайте посмотрим, как мы можем сделать его еще лучше.

Сейчас все наши примеры используют процедурный код, но помните, что контроллеры могут быть любыми валидными объектами типа PHP callbacks. Давайте представим наш контроллер в виде класса.

И, соответственно, обновим определение маршрута.

Довольно простой ход, и его полезность станет очевидна, как только у вас появится больше страничек. Однако, возможно вы заметили один побочный эффект: класс LeapYearController всегда загружен (у нас всегда есть его экземпляр). Даже если запрошенный URL не содержит маршрут leap_year. И это очень плохо для производительности. Все контроллеры для всех маршрутов имеют экземпляр, вне зависимости от запроса. Было бы гораздо лучше, если бы был определен только контроллер, ассоциированный с нужным маршрутом.

Что бы решить эту задачу, и многие другие, мы установим и используем компонент HttpKernel:

Компонент HttpKernel имеет много интересных возможностей, но прямо сейчас нам нужен controller resolver. Controller resolver знает как определять какой контроллер запускать с какими параметрами, основываясь на объекте Request.

Все резолверы контроллеров реализуют следующий интерфейс:

Метод getController() опирается на те же самые правила, что и тот, который мы определили ранее: параметр _controller должен содержать контроллер, ассоциированный с запросом. Также ф-ция getController() может принимать строку, составленную из имени класса и имени метода через два двоеточия, как ‘class::method‘:

Изменим код фреймворка для использования controller resolver из компонента HttpKernel.

Теперь посмотрим, как controller resolver определит параметры контроллера. getArguments() исследует определение контроллера, что бы понять какие параметры в него передавать, используя родное расширение PHP: Reflection.

Метод indexAction() принимает объект Request в качестве параметра. Что бы getArguments() корректно передала его, нужно дать ей небольшую подсказку:

Более интересно, что getArguments так же может передавать любые параметры запроса. Имя параметра метода просто должно совпадать с именем параметра запроса.

Так же можно передать объект Request и параметры запроса одновременно (и порядок не важен).

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

Давайте сделаем передачу параметра запроса $year в наш контроллер:

Controller resolver также позаботится о валидации вызываемого контроллера и его аргументов. В случае проблемы, он выдаст исключение с разъяснением проблемы (не удалось найти класс контроллера, не удалось найти класс метода, неверно определены параметры…)

Вы наверно спросите, при такой гибкости controller resolver, зачем кому-то, придет в голову писать свой собственный (ведь существует же интерфейс)?
Два примера:

  1. В Symfony2, getController() усовершенствован, для поддержки controllers as services;
  2. В FrameworkExtraBundle getArguments() усовершенствована для поддержки конвертеров параметров, где параметры запроса автоматически конвертируются в объекты.

Итак, новая версия фреймворка:

Подумайте только: наш фреймворк, более стабильный, более гибкий чем когда либо, и он все еще занимает меньше 40 строк кода.

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

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

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

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

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