Pull to refresh

Symfony 2.0 краткий обзор, часть 2

Symfony *
Итак, продолжаю осмотр фреймворка Symfony 2.0. В первой части я описал содержимое приложения symfony-sandbox созданного на базе Symfony 2.0. В этой части я загляну в содержимое самого фреймворка.

Перейдя в директорию src/vendor/symfony/src/Symfony приложения, увидим три директории:
  • Components
  • Foundation
  • Framework

В первой части я писал, что сам фреймворк — это набор «бандлов» в этом легко убедиться заглянув в директорию Framework, в которой находятся:
  • Framework/DoctrineBundle: это Doctrine ORM
  • Framework/ProfilerBundle: это друг разработчика — toolbar
  • Framework/SwiftmailerBundle: Swift mailer
  • Framework/WebBundle: web, templating, user
  • Framework/ZendBundle: Zend library, сейчас используется Zend_Log


WebBundle пожалуй самый большой «бандл» из доступных на данный момент. Здесь и Controller от которого наследуется контроллер приложения, и класс User и сессии и templating и util и skeleton для приложения и для «бандла». В общем интересно в него заглянуть, но не в этот раз.

Содержимое Foundation похоже на базовую библиотеку кода, т.е. здесь содержится код, позволяющий всему этому чуду работать как надо. В частности базовый класс ядра, «бандл» ядра, EventDispatcher, универсальный автозагрузчик классов, абстрактный класс Bundle реализующий интерфейс BundleInterface, от которого неследуются все «бандлы».

Ну и содержимое Components — это те самые компоненты, но написанные в стиле PHP 5.3. На данный момент доступны:
  • Components/Console
  • DependencyInjectionContainer
  • EventDispatcher
  • OutputEscaper
  • RequestHandler
  • Routing
  • Templating
  • Yaml
Вот чего пока нет из нужного, так это суб-фреймворка Forms.

Итак, если кратко, то работает это примерно так: при обращении к фронт контроллеру web/index.php создается экземпляр класса ядра приложения в нашем случае HelloKernel, который расширяет класс Symfony\Foundation\Kernel. При создании объекта в конструктор класса передаются два параметра название окружения и флаг включения отладки true или false. В конструторе класса вызываются методы регистрации «бандлов», регистрации путей поиска «бандлов», регистрации корневой директории приложения и определяется имя самого приложения. После чего во фронт контроллере вызывается метод run() в котором и происходит основная работа. И опять же если кратко, то основная работа выглядит так: выполняется метод boot() в котором инициализируется DI контейнер (Dependency Injection Container), при инициализации вызываются методы построения контейнера всех подключенных «бандлов». После этого вызывается метод загрузки настроек приложения. Затем весь этот построенный и сформированный контейнер записывается в кеш в виде класса, чтобы не строить его при каждом запросе, подключается файл из кеша и создается экземпляр этого сформированного класса контейнера.

После этого вызывается метод boot() всех подключенных «бандлов». Затем из контейнера вытаскивается объект запроса, по дефолту это объект класса Symfony\Components\RequestHandler\Request. А затем из контейнера вытаскивается объект обработчика запроса, по дефолту это объект класса Symfony\Components\RequestHandler\RequestHandler, у которого вызывается метод handle() и в качестве параметра ему передается уже полученный объект запроса. Метод handle() должен вернуть объект ответа Symfony\Components\RequestHandler\Response у которого в свою очередь вызывается метод send(), который отвечает за отправку ответа (заголовков и тела). Вот если коротко и грубо, то этим и ограничивается работа ядра. Все остальное лежит на плечах «бандлов».

Каждый «бандл» должен иметь класс реализующий интерфейс Symfony\Foundation\BundleInterface в котором определено всего два метода buildContainer(ContainerInterface $container) регистрирующий в контейнере параметры и сервисы и boot(ContainerInterface $container) который отвечает за загрузку «бандла», загрузка осуществляется уже после того как все параметры и сервисы всех «бандлов» определены в DI контейнере. Большинство «бандлов», а именно все «бандлы» из Symfony/Framework расширяют класс Symfony\Foundation\Bundle и перекрывают лишь метод builderContainer для определения в контейнере своих настроек и сервисов.

Для примера как можно использовать метод boot() класса Bundle. По дефолту в «бандле» WebBundle используется шаблонный движок на базе Symfony\Components\Templating. Но сервис templating.engine в WebBundle определен таким образом, что не позволяет передать в конструктор свои классы Renderer'а, в то время как Symfony\Components\Templating\Engine в конструкторе вторым параметром принимает массив кастомных Renderer'ов. Но благодаря использованию Dependency Injection Container это легкое недоразумение легко исправляется. Для этого в нашем приложении в файле src/Application/HelloBundle/Bundle.php в классе Bundle определим метод:
public function boot(ContainerInterface $container)
{
  $container->getTemplatingService()->setRenderer('name', new Renderer());
}

где класс Renderer — наш кастомный рендерер, а 'name' имя этого рендерера. Теперь при отображении шаблонов можно использовать свой собственный рендерер.

Во всем этом обзоре, я практически не затронул работу из консоли. Внешне все осталось почти так же, за тем исключением, что теперь консольный контроллер создается на уровне приложения, а не на уровне всего проекта, как это было в Symfony 1.x. Но внутри произошли серьезные перемены, появились дополнительные возможности, подробнее с которыми можно познакомиться изучая Components/Console. Появилась и еще одна интересная возможность — Symfony shell. Достаточно запустить hello/console -s и запустится интерактивный консольный сеанс, проще говоря Symfony shell позволяющий выполнять теже самые команды.

Symfony 2.0.0 Shell

Вот в общем и завершился краткий обзор Symfony 2.0. Фреймворк конечно еще сырой, в некоторых ситуациях возникают неожиданные ошибки, некоторых вещей еще нет. Но разработчики фреймворка призывают попробовать и высказать свои пожелания, мнения ну и баг-репорты конечно тоже. Так что велкам!
Ну а я попробую сделать краткие обзоры о Symfony/Components.
Tags:
Hubs:
Total votes 30: ↑22 and ↓8 +14
Views 3.3K
Comments Comments 3