in Профессиональное

Symfony2 book: Основы создания страниц / The Basics of Page Creation

Обновление от Августа 2016: перевод документации Symfony 2 на русский опубликован в виде бесплатной книги на сайте Leanpub. Узнать подробности.

 

Создание новой страницы в Symfony2 это простой процесс, состоящий из 2 шагов:

  • Создание маршрута:
    Маршрут определяет URI (например /about) для вашей страницы, а также контроллер (PHP функция), который Symfony2 должен выполнить, когда URI входящего запроса совпадет шаблоном маршрута;
  • Создание контроллера:
    Контроллер – это PHP функция, которая принимает входящий запрос и трансформирует его в объект Response (ответ).

Нам нравится такой подход, потому что он соответствует тому как работает Web. Каждое взаимодействие в Web инициализируется HTTP запросом. Забота вашего приложения – интерпретировать запрос и вернуть соответствующий ответ. Symfony2 следует этой философии и предлагает вам инструменты и соглашения, для того чтобы ваше приложение оставалось структурированным при росте его сложности.

Страница “Hello Symfony!”

Давайте начнем с классического приложения “Hello World!”. Когда мы закончим, пользователь будет иметь возможность получить персональное приветствие, перейдя по следующему URL:

http://localhost/app_dev.php/hello/Symfony

Вы также сможете заменить “Symfony” на другое имя и получить новое приветствие. Для создания этой страницы мы
пройдем простой путь из двух шагов.

Данное руководство подразумевает, что вы уже скачали Symfony2 и настроили ваш вебсервер. URL, указанный выше, подразумевает, что localhost указывает на web-директорию вашего нового Symfony2 проекта. Если же вы ещё не выполнили этих шагов, рекомендуется их выполнить, прежде чем вы продолжите читать.

Создание Пакета (bundle)

Прежде чем начать, вам необходимо создать пакет (bundle). В Symfony2 пакет напоминает plugin, за исключением того, что весь код вашего приложения будет расположен внутри такого пакета.
Вообще говоря, пакет – это не более чем директория (соответствующая тем не менее пространству имен PHP), которая содержит все что относится к какой-то специфической функции (см. Система пакетов). Для создания пакета с именем AcmeStudyBundle (демо-пакет, который мы создадим в ходе прочтения данной статьи), необходимо выполнить следующую команду (из корня проекта):

  php app/console init:bundle "Acme\StudyBundle" src

Далее, нам необходимо убедиться, что пространство имен Acme загружено – для этого нам надо добавить следующий код в файл app/autoload.php file (см. Автозагрузка):

$loader->registerNamespaces(array(
    'Acme'                         => __DIR__.'/../src',
    // ...
));

Наконец, инициализируем пакет, добавляя его в метод registerBundles класса AppKernel:

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
        new Acme\StudyBundle\AcmeStudyBundle(),
    );
    // ...
    return $bundles;
}

Теперь, когда мы создали и подключили пакет, мы можем начать создание нашего приложения в нём.

Создание маршрута

По умолчанию, конфигурационный файл маршрутизатора в приложении Symfony2, располагается в app/config/routing.yml. Для конфигурирования маршрутизатора, а также любых прочих конфигураций Symfony2, вы можете также использовать XML или PHP формат:

  • YAML
    # app/config/routing.yml
    homepage:
        pattern:  /
        defaults: { _controller: FrameworkBundle:Default:index }
    
    hello:
        resource: "@AcmeStudyBundle/Resources/config/routing.yml"
  • XML
    <!-- app/config/routing.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
     
    <routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
     
        <route id="homepage" pattern="/">
            <default key="_controller">FrameworkBundle:Default:index</default>
        </route>
     
        <import resource="@AcmeStudyBundle/Resources/config/routing.xml" />
    </routes>
  • PHP
    // app/config/routing.php
    use Symfony\Component\Routing\RouteCollection;
    use Symfony\Component\Routing\Route;
     
    $collection = new RouteCollection();
    $collection->add('homepage', new Route('/', array(
        '_controller' => 'FrameworkBundle:Default:index',
    )));
    $collection->addCollection($loader->import("@AcmeStudyBundle/Resources/config/routing.php"));
     
    return $collection;

Первые строки конфигурации определяют, какой код будет вызван для запроса “/” (homepage) и служат примером конфигурации маршрута. Последняя часть более интересна – в ней импортируется другой конфигурационный файл маршрутизатора, который находится внутри AcmeStudyBundle:

  • YAML
    # src/Acme/StudyBundle/Resources/config/routing.yml
    hello:
        pattern:  /hello/{name}
        defaults: { _controller: AcmeStudyBundle:Hello:index }
  • XML
    # src/Acme/StudyBundle/Resources/config/routing.yml
    <!-- src/Acme/StudyBundle/Resources/config/routing.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
     
    <routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
     
        <route id="hello" pattern="/hello/{name}">
            <default key="_controller">AcmeStudyBundle:Hello:index</default>
        </route>
    </routes>
  • PHP
    # src/Acme/StudyBundle/Resources/config/routing.yml
    // src/Acme/StudyBundle/Resources/config/routing.php
    use Symfony\Component\Routing\RouteCollection;
    use Symfony\Component\Routing\Route;
     
    $collection = new RouteCollection();
    $collection->add('hello', new Route('/hello/{name}', array(
        '_controller' => 'AcmeStudyBundle:Hello:index',
    )));
     
    return $collection;

Маршрут состоит из двух основных частей: шаблон, с которым сравнивается URI, а также массив параметров по умолчанию (defaults), в котором указывается контроллер, который необходимо выполнить. Синтаксис указателя места заполнения (placeholder) в шаблоне ({name}) – это групповой символ (wildcard). Он означает, что URI /hello/Ryan, /hello/Fabien, а также прочие, походие на них, будут соответствовать этому маршруту. Параметр, определённый указателем {name}, также будет передан в наш контроллер, так что мы сможем использовать его, чтобы поприветствовать пользователя.

Система маршрутизации имеет еще множество замечательных функций для создания гибких и функциональных структур URI в нашем приложении. За дополнительной информацией вы можете обратиться по ссылке Routing (увы, пока без перевода).

Создание Контроллера

Когда URI вида /hello/Ryan обнаруживается приложением в запросе, маршрут hello сработает и будет вызван контроллер AcmeStudyBundle:Hello:index. Следующим нашим шагом будет создание этого контроллера. В действительности, контроллер – это не что иное, как метод PHP класса, который мы создаем, а Symfony выполняет. Это то место, где приложение, используя информацию из запроса, создает запрошенный ресурс. За исключением некоторых особых случаев, результатом работы контроллера всегда является объект Symfony2 Response:

// src/Acme/StudyBundle/Controller/HelloController.php
 
namespace Acme\StudyBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
 
class HelloController
{
    public function indexAction($name)
    {
        return new Response('<html><body>Hello '.$name.'!</body></html>');
    }
}

Этот контроллер предельно прост: он создает новый объект Response, чьим первым аргументом является контент, который будет использован для создания ответа (в нашем случае это маленькая HTML-страница, код которой мы указали прямо в контроллере).
Примите мои поздравления! ;)) После создания маршрута и контроллера, вы уже имеете полноценную страницу! Если вы все настроили корректно, ваше приложение должно поприветствовать вас:

  http://localhost/app_dev.php/hello/Ryan

Опциональным (но как правило востребованным) третьим шагом является создание шаблона.

Контроллер – это главная точка входа для вашего кода и ключевой ингридиет при создании страниц. Больше информации о контроллерах вы можете найти тут: Controller Chapter (пока также без перевода).

Создание шаблона

Шаблоны позволяют нам вынести разметку страниц (HTML код как вравило) в отдельный файл и повторно использовать различные части шаблона страницы. Вместо того чтобы писать код внутри контроллера, воспользуемся шаблоном:

// src/Acme/StudyBundle/Controller/HelloController.php
 
namespace Acme\StudyBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 
class HelloController extends Controller
{
    public function indexAction($name)
    {
        return $this->render('AcmeStudyBundle:Hello:index.html.twig', array('name' => $name));
 
        // render a PHP template instead
        // return $this->render('AcmeStudyBundle:Hello:index.html.php', array('name' => $name));
    }
}

Для того, чтобы использовать метод render(), необходимо отнаследоваться от класса SymfonyBundleFrameworkBundleControllerController, который добавляет несколько методов для быстрого вызова для часто употребляемых функций в контроллере.

Метод render() создает объект Response, заполненный содержанием обработанного (рендереного) шаблона. Как и любой другой контроллер, вы в конце концов вернете объект Response.
Обратите внимание, что есть две различные возможности рендеринга шаблонов. Symfony2 по-умолчанию, поддерживает 2 языка шаблонов: классические PHP-шаблоны и простой, но мощный язык шаблонов Twig. Но не пугайтесь, вы свободны в выборе того или иного из них, кроме того вы можете использовать оба в рамках одного проекта.
Контроллер отображает шаблон AcmeStudyBundle:Hello:index.html.twig, который использует следующие соглашения: BundleName:ControllerName:TemplateName
Таким образом, AcmeStudyBundle – это имя пакета, Hello – это контроллер и index.html.twig это шаблон:

  • Twig
    1
    2
    3
    4
    5
    6
    
    {# src/Acme/StudyBundle/Resources/views/Hello/index.html.twig #}
    {% extends '::layout.html.twig' %}
     
    {% block body %}
        Hello {{ name }}!
    {% endblock %}
  • PHP
    <!-- src/Acme/StudyBundle/Resources/views/Hello/index.html.php -->
    <?php $view->extend('::layout.html.php') ?>
     
    Hello <?php echo $view->escape($name) ?>!

Давайте рассмотрим подробнее шаблон Twig:

  • строка 2: Токен extends определяет родительский шаблон. Таким образом сам шаблон однозначным
    образом определяет родителя (layout) внутрь которого он будет помещен.
  • строка 4: Токен block означает, что все внутри него будет помещено в блок с именем body.
    Как мы увидим ниже, это уже обязанность родительского шаблона (layout.html.twig) – полностью отобразить блок body.

Родительский шаблон, ::layout.html.twig, не включает в себя ни имени пакета, ни контроллера (отсюда и двойное двоеточие в начале имени (::)). Это означает что шаблон располагается вне пакета в директории app:

  • Twig
    {# app/Resources/views/layout.html.twig #}
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>{% block title %}Hello Application{% endblock %}</title>
        </head>
        <body>
            {% block body %}{% endblock %}
        </body>
    </html>
  • PHP
    <!-- app/Resources/views/layout.html.php -->
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title><?php $view['slots']->output('title', 'Hello Application') ?></title>
        </head>
        <body>
            <?php $view['slots']->output('_content') ?>
        </body>
    </html>

Базовый шаблон определяет HTML разметку блока body, который мы определили в шаблоне index.html.twig.
Он также отображает блок title, который мы также можем определить в index.html.twig. Так как мы не определили блок title в дочернем шаблоне, он примет значение по умолчанию – “Hello Application”.
Шаблоны являются мощным инструментом по организации и отображению контента ваших страниц – HTML разметки, CSS стилей, а также всего прочего, что может потребоваться вернуть контроллеру. Но шаблонизатор – это просто средство для достижения цели. А цель состоит в том, чтобы каждый контроллер возвращал объект Response. Таким образом, шаблоны мощный, но опциональный инструмент для создания контента для объекта Response.

Структура директорий

Мы прочитали всего лишь после нескольких коротких секций, а вы уже уяснили (ведь уяснили же?! правда? ;)) философию создания и отображения страниц в Symfony2. Поэтому без лишних слов мы приступим к изучению того, как организованы и структурированы проекты Symfony2. К концу этой секции вы будете знать где найти и куда поместить различные типы файлов. И более того, будет понимать – почему! )
Изначально созданный очень гибким, по умолчанию каждое Symfony приложение имеет одну и ту же базовую (и рекомендуемую) структуру директорий:

  • app/: Эта директория содержит настройки приложения;
  • src/: Весь PHP код проекта находится в этой директории;
  • vendor/: Здесь размещаются сторонние библиотеки;
  • web/: Это корневая директория, видимая web-серверу и содержащая доступные пользователям файлы;

Директория Web

Web-директория – это дом для всех публично-доступных статических файлов, таких как изображения, таблицы стилей и JavaScript файлы. Тут также располагаются все фронт-контроллеры:

// web/app.php
require_once __DIR__.'/../app/bootstrap.php';
require_once __DIR__.'/../app/AppKernel.php';
 
use Symfony\Component\HttpFoundation\Request;
 
$kernel = new AppKernel('prod', false);
$kernel->handle(Request::createFromGlobals())->send();

Файл фронт-контроллера (в примере выше – app.php)- это PHP файл, который выполняется, когда используется Symfony2 приложение и в его обязанности входит использование Kernel-класса, AppKernel, для запуска приложения.

Наличие фронт-контроллера означает возможность использования более гибких URL, отличных от тех, что используются в типичном “плоском” PHP-приложении. Когда используется фронт-контроллер, URL формируется следующим образом:

    http://localhost/app.php/hello/Ryan

Фронт-контроллер app.php выполняется и URI /hello/Ryan направляется внутри приложения с использованием конфигурации маршрутизатора. С использованием правил mod_rewrite для Apache вы можете перенаправлять все запросы (на физически не существующие URI) на app.php, чтобы явно не указывать его в URL:

  http://localhost/hello/Ryan

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

Директория приложения

Как вы уже видели во фронт-контроллере, класс AppKernel – это точка входа приложения и он отвечает за его конфигурацию. Как таковой, этот класс расположен в директории app/. Этот класс должен реализовывать три метода, которые определяются все, что Symfony необходимо знать о вашем приложении. Вам даже не нужно беспокоиться о реализации этих методов, когда начинаете работу – они уже реализованы с кодом по-умолчанию.

  • registerBundles(): Возвращает массив всех пакетов, необходимых для запуска приложения (см. секцию Пакетная система);
  • registerContainerConfiguration(): Загружает главный конфигурационный файл (см. секцию
    Конфигурация приложения);
  • registerRootDir(): Возвращает корневую директорию приложения (app/ по умолчанию).

Изо дня в день вы будете использовать директорию app/ в основном для того, чтобы модифицировать конфигурацию и настройки маршрутизатора в директории app/config/ (см. Конфигурация приложения).
Также в app/ содержится кеш (app/cache), директория для логов (app/logs) и директория для ресурсов уровня приложения (app/Resources). Об этих директориях подробнее будет рассказано в других главах.

Автозагрузка
При инициализации приложения подключается особый файл: app/autoload.php. Этот файл отвечает за автозагрузку всех файлов из директорий src/ и vendor/.
С использованием автозагрузки вам больше не придется беспокоиться об использовании выражений include или require. Вместо этого, Symfony2 использует пространства имен классов, чтобы определить их расположение и автоматически подключить файл класса, в случае если класс вам понадобится:

$loader->registerNamespaces(array(
  'Acme'                         => __DIR__.'/../src',
  // ...
));

При такой конфигурации, Symfony2 будет искать в директории src классы из пространства имен Acme (вы скорее всего будете использовать наименование вашей компании). Для того чтобы эта парадигма работала, необходимо чтобы имя класса и путь к нему соответствовали следующему шаблону:

Class Name:
  Acme\StudyBundle\Controller\HelloController
Path:
  src/Acme/StudyBundle/Controller/HelloController.php

Файл app/autoload.php конфигурирует автозагрузчик и указывает ему, где искать классы из различных пространств имен и при необходимости может быть гибко настроен. Если вы хотите узнать больше об автозагрузке, смотрите статью в “поваренной книге” (без перевода): How to autoload Classes.

Директория исходных кодов проекта (src)

Если вкратце, директория src/ содержит весь код приложения. Фактически, во время разработки, большую часть работ вы будете производить именно в этой директории. По умолчанию, директория src/ нового проекта пуста. Когда вы начинаете разработку, вы постепенно наполняете ее пакетами, которые содержат код приложения.
Но что же собственно из себя представляет сам пакет?

Система пакетов

Пакет чем-то схож с плагином, но он ещё лучше. Ключевое отличие состоит в том, что всё есть пакет в Symfony2, включая функционал ядра и код вашего приложения.
Пакеты – это граждане высшего сорта в Symfony2. Они дают вам возможность использовать уже готовые пакеты, которые вы можете найти по адресу symfony2bundles.org. Вы также можете там выкладывать свои пакеты. Они также дают возможность легко и просто выбрать, какие именно функции подключить в вашем приложении.

Здесь мы рассмотрим лишь основы, более детальную информацию по пакетам вы можете найти в главе Пакеты.

Пакет это просто структурированный набор файлов и директорий, который реализует одну конкретную функцию. Вы можете создать BlogBundle или ForumBundle или же пакет для управления пользователями (такие пакеты уже есть и даже с открытым исходным кодом). Каждая директория содержит все необходимое для реализации этой конкретной функции, включая PHP файлы, шаблоны, стили, клиентские скрипты, тесты и все что ещё потребуется. Каждый аспект реализации функции находится в своём пакете и каждая функция располагается в своем собственном пакете.
Приложение состоит из пакетов, которые объявлены в методе registerBundles() класса AppKernel.

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
        new Symfony\Bundle\SecurityBundle\SecurityBundle(),
        new Symfony\Bundle\TwigBundle\TwigBundle(),
        new Symfony\Bundle\MonologBundle\MonologBundle(),
        new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
        new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
        new Symfony\Bundle\AsseticBundle\AsseticBundle(),
        new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
        new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
 
        // register your bundles
        new Acme\StudyBundle\AcmeStudyBundle(),
    );
 
    if (in_array($this->getEnvironment(), array('dev', 'test'))) {
        $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
    }
 
    return $bundles;
}

Используя метод registerBundles(), вы получаете полный контроль над теми пакетами, которые используются вашим приложением (включая пакеты, входящие в состав ядра Symfony).

Вообще говоря, пакет может располагаться где угодно, если конечно его расположение не мешает автозагрузчику Symfony2. Например, если AcmeStudyBundle расположен в директории src/Acme, озаботьтесь тем, чтобы пространство имён Acme было добавлено в файл app/autoload.php и было направлено (mapped) на директорию src.

Создание пакета

Чтобы показать вам как проста система пакетов, давайте создадим новый пакет, назовём его AcmeTestBundle и активируем его.
В первую очередь, создадим директорию src/Acme/TestBundle/ и добавим в неё файл AcmeTestBundle.php:

// src/Acme/TestBundle/AcmeTestBundle.php
namespace Acme\TestBundle;
 
use Symfony\Component\HttpKernel\Bundle\Bundle;
 
class AcmeTestBundle extends Bundle
{
}

Наименование AcmeTestBundle следует соглашениям по именованию пакетов .

Этот пустой класс – единственное, что необходимо создать для минимальной комплектации пакета. Не смотря на то, что класс пуст, он обладает большим потенциалом и позволяет настраивать поведение пакета.
Теперь, когда мы создали пакет, его нужно активировать в классе AppKernel:

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
 
        // register your bundles
        new Acme\TestBundle\AcmeTestBundle(),
    );
 
    // ...
 
    return $bundles;
}

И, хотя наш новый пакет пока ничего не делает, он готов к использованию. Symfony также предлагает интерфейс для командной строки для создания базового каркаса пакета:

php app/console init:bundle "Acme\TestBundle" src

Каркас пакета создаёт базовый контроллер, шаблон и маршрут, которые можно настроить. Мы еще вернёмся к инструментам командной строки позже.

Когда создаёте новый пакет, или используете сторонние пакеты, убедитесь, что пакет активирован в registerBundles().

Структура директории пакета

Структура директории пакета проста и гибка. По умолчанию, система пакетов следует некоторым соглашениям, которые помогают поддерживать стилевое единообразие во всех пакетах Symfony2. Давайте взглянем на пакет AcmeStudyoverBundle, так как он содержит наиболее основные элементы пакета:

  • Controller/ содержит контроллеры (например HelloController.php);
  • Resources/config/ место для конфигурационных файлов, включая конфигурацию маршрутизатора (например routing.yml);
  • Resources/views/ шаблоны, сгруппированные по имени контроллера (например Hello/index.html.twig);
  • Resources/public/ публично доступные ресурсы (картинки, стили…), которые будут скопированы или связаны символической ссылкой с web/ директорией;
  • Tests/ содержит все тесты.

Пакет может быть как маленьким, так и большим – в зависимости от задачи, которую он реализует. Он содержит лишь те файлы, которые нужны – и ничего более.
В других главах книги вы также узнаете как работать с базой данных, как создавать и валидировать формы, создавать файлы переводов, писать тесты и много чего ещё. Все эти объекты в пакете имеют определенную роль и место.

Настройка приложения

Приложение состоит из набора пакетов, реализующих все необходимые функции вашего приложения. Каждый пакет может быть настроен при помощи конфигурационных файлов, написанных на YAML, XML или PHP. По умолчанию, основной конфигурационный файл расположен в директории app/config/ и называется config.yml, config.xml или config.php, в зависимости от предпочитаемого вами формата.

  • YAML
    # app/config/config.yml
    framework:
        charset:       UTF-8
        error_handler: null
        csrf_protection:
            enabled: true
            secret: xxxxxxxxxx
        router:        { resource: "%kernel.root_dir%/config/routing.yml" }
        validation:    { enabled: true, annotations: true }
        templating:    { engines: ['twig'] } #assets_version: SomeVersionScheme
        session:
            default_locale: en
            lifetime:       3600
            auto_start:     true
     
    # Twig Configuration
    twig:
        debug:            %kernel.debug%
        strict_variables: %kernel.debug%
  • XML
    <!-- app/config/config.xml -->
    <framework:config charset="UTF-8" error-handler="null" cache-warmer="false">
        <framework:router resource="%kernel.root_dir%/config/routing.xml" cache-warmer="true" />
        <framework:validation enabled="true" annotations="true" />
        <framework:session default-locale="en" lifetime="3600" auto-start="true" />
        <framework:templating assets-version="SomeVersionScheme" cache-warmer="true">
            <framework:engine id="twig" />
        </framework:templating>
        <framework:csrf-protection enabled="true" secret="xxxxxxxxxx" />
    </framework:config>
     
    <!-- Twig Configuration -->
    <twig:config debug="%kernel.debug%" strict-variables="%kernel.debug%" cache-warmer="true" />
  • PHP
    $container->loadFromExtension('framework', array(
        'charset'         => 'UTF-8',
        'error_handler'   => null,
        'csrf-protection' => array('enabled' => true, 'secret' => 'xxxxxxxxxx'),
        'router'          => array('resource' => '%kernel.root_dir%/config/routing.php'),
        'validation'      => array('enabled' => true, 'annotations' => true),
        'templating'      => array(
            'engines' => array('twig'),
            #'assets_version' => "SomeVersionScheme",
        ),
        'session' => array(
            'default_locale' => "en",
            'lifetime'       => "3600",
            'auto_start'     => true,
        ),
    ));
     
    // Twig Configuration
    $container->loadFromExtension('twig', array(
        'debug'            => '%kernel.debug%',
        'strict_variables' => '%kernel.debug%',
    ));

О том как выбрать какой файл/формат загружать – мы рассмотрим в следующей секции – Окружения.

Каждый параметр верхнего уровня, например framework или twig, определяет настройки конкретного пакета. Например, ключ framework определяет настройки ядра Symfony FrameworkBundle и включает настройки маршрутизации, шаблонизатора и прочих ключевых систем.
Пока же нам не стоит беспокоиться о конкретных настройках в каждой секции. Файл настроек по умолчанию содержит все необходимые параметры. По ходу чтения прочей документации вы ознакомитесь со всеми специфическими настройками.

Форматы конфигураций
Во всех главах книги все примеры конфигураций будут показаны во всех трех форматах (YAML, XML and PHP). Каждый из них имеет свои достоинства и недостатки. Выбор же формата целиком зависит о ваших предпочтений:

  • YAML: Простой, понятный и читабльный;
  • XML: В разы более мощный, нежели YAML. Поддерживается многими IDE (autocompletion;
  • PHP: Очень мощный, но менее читабельный, чем стандартные форматы конфигурационных файлов.

Окружения

Приложение можно запускать в различных окружениях. Различные окружения используют один и тот же PHP код (за исключением фронт-контроллера), но могут иметь совершенно различные настройки. Например, dev окружение ведет лог ошибок и замечаний, в то время как prod окружение логгирует только ошибки. В dev некоторые файлы пересоздаются при каждом запросе, но кешируются в prod окружении. В то же время, все окружения одновременно доступны на одной и той же машине.
Проект Symfony2 по умолчанию имеет три окружения (dev, test и prod), хотя создать новое окружение не сложно. Вы можете смотреть ваше приложение в различных окружениях просто меняя фронт-контроллеры в браузере. Для того чтобы отобразить приложение в dev окружении, откройте его при помощи фронт контроллера app_dev.php:

  http://localhost/app_dev.php/hello/Ryan

Если же вы хотите посмотреть, как поведёт себя приложение в продуктовой среде, вы можете вызвать фронт-контроллер prod:

  http://localhost/app.php/hello/Ryan

Если вы откроете файл web/app.php, вы обнаружите, что он однозначно настроен на использование prod окружения:

$kernel = new AppCache(new AppKernel('prod', false));

Вы можете создать новый фронт-контроллер для нового окружения просто скопировав этот файл и изменив prod на другое значение.

Так как prod окружение оптимизировано для скорости, настройки, маршруты и шаблоны Twig компилируются в плоские PHP классы и кешируются. Когда вы хотите посмотреть изменения в продуктовом окружении, вам потребуется удалить эти файлы чтобы они пересоздались автоматически:

  rm -rf app/cache/*

Тестовое окружение (test) используется при запуске автотестов и его нельзя напрямую открыть через браузер. Подробнее об это можно почитать в главе про тестирование.

Настройка окружений

Класс AppKernel отвечает за загрузку конфигурационных файлов:

// app/AppKernel.php
public function registerContainerConfiguration(LoaderInterface $loader)
{
    $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}

Мы уже знаем, что расширение .yml может быть изменено на .xml или .php, если вы предпочитаете использовать XML или PHP. Имейте также в виду, что каждое окружение загружает свои собственные настройки. Рассмотрим конфигурационный файл для dev окружения.

  • YAML
    # app/config/config_dev.yml
    imports:
        - { resource: config.yml }
    
    framework:
        router:   { resource: "%kernel.root_dir%/config/routing_dev.yml" }
        profiler: { only_exceptions: false }
    
    web_profiler:
        toolbar: true
        intercept_redirects: true
    
    zend:
        logger:
            priority: debug
            path:     %kernel.logs_dir%/%kernel.environment%.log
  • XML
    <!-- app/config/config_dev.xml -->
    <imports>
        <import resource="config.xml" />
    </imports>
     
    <framework:config>
        <framework:router resource="%kernel.root_dir%/config/routing_dev.xml" />
        <framework:profiler only-exceptions="false" />
    </framework:config>
     
    <webprofiler:config
        toolbar="true"
        intercept-redirects="true"
    />
     
    <zend:config>
        <zend:logger priority="info" path="%kernel.logs_dir%/%kernel.environment%.log" />
    </zend:config>
  • PHP
    // app/config/config_dev.php
    $loader->import('config.php');
     
    $container->loadFromExtension('framework', array(
        'router'   => array('resource' => '%kernel.root_dir%/config/routing_dev.php'),
        'profiler' => array('only-exceptions' => false),
    ));
     
    $container->loadFromExtension('web_profiler', array(
        'toolbar' => true,
        'intercept-redirects' => true,
    ));
     
    $container->loadFromExtension('zend', array(
        'logger' => array(
            'priority' => 'info',
            'path'     => '%kernel.logs_dir%/%kernel.environment%.log',
        ),
    ));

Ключ imports похож по действию на выражение include в PHP и гарантирует что главный конфигурационный файл (config.yml) будет загружен в первую очередь. Остальной код корректирует конфигурацию по-умолчанию для увеличения порога логгирования и прочих настроек, специфичных для разработки.
Оба окружения – prod и test следуют той же модели: каждое окружение импортирует базовые настройки и модифицирует их значения для своих нужд.

Заключение

Поздравляем! Вы усвоили все фундаментальные аспекты Symfony2 и обнаружили, какими лёгкими и в то же время гибкими они могут быть. И, поскольку на подходе ещё много интересного, обязательно запомните следующие положения:

  • создание страниц – это три простых шага, включающих маршрут, контроллер и (опционально) шаблон;
  • Каждое приложение должно состоять только из 4х директорий: web/ (ассеты и фронт-контроллеры), app/ (настройки), src/ (пакеты), и vendor/ (сторонние библиотеки);
  • Каждая функция в Symfony2 (включая ядро фреймворка) должна располагаться внутри пакета, который представляет собой структурированный набор файлов, реализующих эту функцию;
  • настройки каждого пакета располагаются в директории app/config и могут быть записаны в формате YAML, XML or PHP;
  • каждое окружение доступно через свой отдельный фронт-контроллер (например app.php и app_dev.php) и заружает отдельный файл настроек;

Далее, каждая глава книги познакомит вас с все более и более мощными инструментами и более глубокими концепциями. Чем больше вы знаете о Symfony2, тем больше вы будете ценить гибкость его архитектуры и его обширные возможности для быстрой разработки приложений.

Write a Comment

Comment

*

18 Comments

    • Да, но я глядел с час назад, не было еще. Плюс видимо будут стабилизировать то что есть судя по заявлению Фабиена (т.е. грандиозных перестановок не ожидается). Это гут. Но конечно хотелось бы еще пяток жизненно необходимых пакетов от производителя так сказать. А то на symfony2bundles все еще сырее чем сама симфони2 )

  1. Уже читал на английском, но с удовольствием перечитал на русском. Отличная работа! Быстрее бы Marketplace заработал, а то действительно стующих бандлов не много.

    • Спасиб ) Еле осилил ) длинный зараза, и с внутренним форматированием… А насчет пакетов – согласен, очень мало стоящего. Да и еще каждый вещь в себе, почти без документации… ну и т.п.

        • 1. админка (бандл развивается)
          2. управление пользователями, правами и т.д. (что то видел)
          3. бандл для интеграции с jquery or dojo.
          4. навигация, хлебные крошки
          5. всякие бандлы cms, галерей, блогово, новостей
          6. бандл для взаимодействия с платежными системами
          Перечелсять можно долго 🙂

          • о, да, навигация – очень актуальная вещь. Есть MenuBundle, но она имхо очень слабая.

  2. Или это ошибка или у меня не сконтачилось:

    При создании и розширении шаблона нужно поменять

    {% extends ‘::layout.html.twig’ %}
    на
    {% extends ‘AcmeStudyBundle::layout.html.twig’ %}

    • Если layout лежит в app, то AcmeStudyBundle указывать не надо, начколько я помню, но с тех пор уже вышла пара бета-версий и четыре Pre-release )) Возможно что-то поменялось.