Вступительное слово



В этой серии статей мы рассмотрим создание блога на Symfony 2. За основу взят и переведён проект http://tutorial.symblog.co.uk/ разработчика Даррена Риса ( Darren Rees ). Перед написанием данной статьи я обратился к нему, и он дал своё согласие на перевод с поправками под версию Symfony 2.8 lts, за что я ему очень благодарен.

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

Также вы знаете, что по Symfony2 есть куча документации и статей, в том числе на Хабре, видео на youtube и т.д., так что этот проект не является чем-то новым.

Мне бы очень хотелось, чтобы мы разработали этот проект вместе с вами, очень надеюсь, что все, кто прикоснётся к этому руководству, извлечёт для себя какую-то пользу.

Проект на Github

Поехали!

Введение


Реализовывать наш проект я буду в ОС Windows 10, IDE PHPStorm 2016. Вам тоже рекомендую использовать эту IDE, но если вы используете что-то другое будь, то CodeLobster, NotePad++ и т.д., ничего страшного.

Руководство разделено на несколько частей, каждая из которых охватывает различные аспекты Symfony 2 и ее компонентов.

Части руководства


[Часть 1] — Конфигурация Symfony2 и шаблонов
[Часть 2] — Страница с контактной информацией: валидаторы, формы и электронная почта
[Часть 3] — Модель Блога: Использование Doctrine 2 и Фикстур данных
[Часть 4] — Модель комментариев: Добавление комментариев, Репозиторий Doctrine 2 и Миграции
[Часть 5] — Настройка view: расширения Twig, Sidebar и Assetic
[Часть 6] — Тестирование: Unit и Functional с помощью PHPUnit

Это руководство ставит своей целью охватить часто встречающиеся задачи, с которыми вы сталкиваетесь при создании веб-сайтов с помощью Symfony2.

1. Бандлы
2. Контроллеры
3. Шаблоны (Использование Twig)
4. Модель – Doctrine 2
5. Миграции
6. Фикстуры данных
7. Валидаторы
8. Формы
9. Маршрутизация
10. Asset
11. Электронная почта
12. Безопасность
13. Пользователь и сессии
14. Генерация CRUD (Create Read Update Delete — Создание Чтение Обновление Удаление)

Symfony2 является легко настраиваемым фреймворком и предоставляет ряд различных способов для выполнения одной и той же задачи. Примером этого может являться возможность написания параметров конфигурации в форматах YAML, XML, PHP или аннотациях, а также создания шаблонов с помощью Twig или PHP. Чтобы сделать это руководство как можно более простым мы будем использовать формат YAML и аннотации для конфигурации и Twig для шаблонов.

Часть 1



1. Настройка приложения Symfony2
2. Symfony2 Бандлы
3. Маршрутизация
4. Контроллеры
5. Шаблонизатор Twig

Установка Symfony2 с помощью Composer на ОС Windows
Установите Composer глобально для ОС Windows можно скачать установщик по ссылке https://getcomposer.org/Composer-Setup.exe так же у вас должен быть установлен PHP в моём случае версия PHP 5.6

Обычно он входит в состав серверных платформ типа Open Server, а также включает в себя необходимый нам MySQL и множество других утилит так же вы можете использовать XAMPP или что-то другое на ваш вкус.

Далее откройте консоль, перейдите в каталог, в котором хотите разместить свой проект, и введите:

php -r "file_put_contents('symfony', file_get_contents('https://symfony.com/installer'));"

После того, как установщик скачается введите:

symfony new название_вашего_проекта 2.8

К слову, как установить Symfony 2, вы всегда можете посмотреть на официальном сайте фреймворка.

В нашем же случае мы будем использовать PHPStorm c плагином для Symfony для установки фреймворка, так как это более простой вариант. Для этого Откройте PHPStorm нажмите на Create new Project и создайте новый проект.



Далее выберите Symfony Installer укажите путь к папке, в которую будет установлен проект, версию фреймворка (в нашем случае 2.8.6 lts), а так же путь к php.exe и нажмите Create.



Когда Symfony2 установится, нам понадобится запустить сервер в консоли из папки проекта, делается это командой:

php app/console server:run



Чтобы постоянно не прописывать команду для запуска сервера, мы можем попросить PHPStorm делать это за нас
  • Для этого нажмите на кнопку в панели:


    1. Выберите Edit Configurations
    2. Нажмите на зелёный плюс и добавьте PHP script
    3. Укажите имя
    4. Путь до файла console.php в вашем проекте
    5. В аргументах пропишите server:run и нажмите Ok


  • В панели появится значок Play для запуска скрипта с аргументом, после чего нам достаточно будет нажать на этот значок для запуска сервера.




Сервер запустился, и наш сайт стал доступным по адресу http://127.0.0.1:8000/ и http://localhost:8000/. У вас должна отобразиться вот такая страничка:



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



Это панель инструментов разработчика даёт вам ценную информацию о состоянии приложения. Информацию, включая время выполнения скрипта, использование памяти, запросов к базе данных, состояния аутентификации и многое другое. По умолчанию панель инструментов отображается только при работе в окружении Dev, так как отображение панели инструментов в окружении Prod вызовет большой риск для безопасности, поскольку позволяет увидеть много «внутренностей» вашего приложения.

Настройка Symfony


Откройте файл app/config/parameters.yml и укажите данные для вашей базы данных: логин, пароль и т.д. В моём случае это значения по умолчанию.



Бандлы: Symfony2


Бандл является основным строительным блоком любого приложения Symfony2, на самом деле Symfony2 сам по себе является Бандлом. Бандлы позволяют отделять функциональные возможности друг от друга. Мы создадим Бандл для нашего сайта в пространстве имен Blogger. Если вы не знакомы с пространствами имен в PHP вы должны потратить некоторое время на их изучение, так как они широко используются в Symfony2.

Совет

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

Создание Бандла


Совет

Не забудьте удалить бандл, устанавливаемый по умолчанию (он нам не понадобится) для этого:

  • Удалите папку AppBundle из каталога src
  • Удалите строчку new AppBundle\AppBundle() из зарегистрированных Бандлов, в файле app/AppKernel.php
  • удалите папку default по адресу app/Resources/views
  • удалите эти строки:

    app:
        resource: "@AppBundle/Controller/"
        type:     annotation
    

    из файла app/config/routing.yml


Для инкапсуляции функциональности блога, мы создадим Blog бандл. Это “дом” всех необходимых файлов, и он легко может быть использован в другом приложении Symfony2. Symfony2 предоставляет ряд команд, чтобы помочь нам при выполнении типичных операций. Одной из таких команд является команда генерации бандлов.

Чтобы сгенерировать бандл, выполните следующую команду в консоли из папки проекта:

php app/console generate:bundle 

Совет

Вы так же можете написать:

php app/console gen:bun 

Symfony поймёт такую команду.

Вам будет представлен ряд подсказок, которые позволяют настроить бандл.

  1. Нас спросят, будем ли мы использовать этот бандл в других приложениях
    отвечаем yes :
    Are you planning on sharing this bundle across multiple applications? [no]: yes
  2. Указываем пространство имён у нас оно будет Blogger/BlogBundle:
    Bundle namespace: Blogger/BlogBundle
  3. Далее путь установки Бандла:
    Target Directory [src/]:
    Оставляем по умолчанию, нажимаем Enter
  4. Так же нужно указать формат файла конфигурации мы выберем yml:
    Configuration format (annotation, yml, xml, php) [xml]: yml

Мы создали бандл, при этом на заднем плане автоматически создан маршрут, и бандл зарегистрован в файле app/AppKernel.php.

Совет

Вы не обязаны использовать генератор, который предоставляет Symfony2, он создан только для того, чтобы помочь вам. Вы могли бы вручную создать структуру папок и файлов Бандла. В то время как использование генератора не является обязательным, он даёт некоторые преимущества, для получения работающего пакета. Одним из таких примеров является автоматическая регистрация Бандла.

Регистрация Бандла


Наш новый пакет BloggerBlogBundle был зарегистрирован в ядре и находится в app/AppKernel.php. Symfony2 требует регистрации всех бандлов, которые приложение должно использовать. Вы также заметите, что некоторые бандлы зарегистрированы только в Dev или Test средах. Загрузка этих бандлов в Prod среде вызовет дополнительную нагрузку. Ниже показано, как BloggerBlogBundle был зарегистрирован.

// app/AppKernel.php
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ..
            new Blogger\BlogBundle\BloggerBlogBundle(),
        );
        // ..

        return $bundles;
    }

    // ..
}

Маршрутизация


Маршрут Бандла был импортирован в основной файл маршрутизации приложения, расположенного в app/config/routing.yml.

# app/config/routing.yml

blogger_blog:
    resource: "@BloggerBlogBundle/Resources/config/routing.yml"
    prefix:   /


Префикс позволяет сделать так чтобы весь BloggerBlogBundle был доступен по адресу с префиксом. В нашем случае мы решили установить значение по умолчанию — /.

Т.е. сейчас наш сайт доступен по адресу http://localhost:8000 если же вы хотите, чтобы ваш сайт был доступен по адресу http://localhost:8000/blogger измените на prefix: /blogger.

Структура по умолчанию


В директории src был создан бандл. Он начинается на верхнем уровне с папки Blogger, который указывает непосредственно на пространство имен Blogger. Дальше идёт папка BlogBundle, которая содержит наш Бандл. Содержание этой папки будет рассмотрено, в процессе прохождения данного руководства. Если вы знакомы с MVC фреймворками, некоторые из папок будут вам знакомы.

Маршрутизация бандла


Файл маршрутов BloggerBlogBundle расположен в src/Blogger/BlogBundle/Resources/config/routing.yml и содержит следующий маршрут:

blogger_blog_homepage:
    path:     /
    defaults: { _controller: BloggerBlogBundle:Default:index }

Маршрутизация состоит из шаблона и некоторых настроек по умолчанию. Шаблон сверяется с URL, и параметры по умолчанию указывают контроллеру выполниться, если маршрут совпадает. Маршрут не определяет HTTP методов.

Если маршрут соответствует всем указанным критериям он будет выполнен с помощью опции _controllerпо умолчанию. Опция _controller определяет логическое имя контроллера, который позволяет Symfony2 определять путь к конкретному файлу. Приведенный выше пример будет вызывать функцию index action в контроллере по умолчанию, который находится здесь: src/Blogger/BlogBundle/Controller/DefaultController.php.

Контроллер


Контроллер в этом примере очень прост. Класс DefaultController расширяет Controller класс, который обеспечивает некоторые полезные методы, такие как метод представления (render), используемый ниже. Наша функция ничего не делает, она только лишь вызывает метод представления (render) с указанием index.html.twig шаблона в папке BloggerBlogBundle.

Формат имени шаблона: Бандл: Контроллер: Шаблон. В нашем примере это BloggerBlogBundle:Default:index.html.twig, который отображает index.html.twigшаблон, в папке view по умолчанию в BloggerBlogBundle или физически файл src/Blogger/BlogBundle/Resources/views/Default/index.html.twig.

Различные варианты форматов шаблона могут быть использованы для отображения шаблонов из разных местоположений приложения и его бандлов. Мы увидим это позже в этой части.

<?php

namespace Blogger\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    public function indexAction()
    {
        return $this->render('BloggerBlogBundle:Default:index.html.twig');
    }
}


Шаблон (View)


Как вы можете видеть шаблон очень прост. Он выводит только лишь надпись:

{# src/Blogger/BlogBundle/Resources/views/Default/index.html.twig #}

Hello World!

Чистка


Почистим немного наш бандл, т.к. некоторые файлы, созданные генератором, нам не нужны. Файл контроллера src/Blogger/BlogBundle/Controller/DefaultController.php может быть удалён так же, как и папка Default src/Blogger/BlogBundle/Resources/views/Default.

И, наконец, удалите маршрут, расположенный в src/Blogger/BlogBundle/Resources/config/routing.yml.

Шаблоны


У нас есть 2 варианта по умолчанию для использования Symfony2 шаблонов; Twig и PHP. Вы можете, конечно, не использовать ни один из них и выбрать другую библиотеку. Это возможно благодаря Symfony2 Dependency Injection Container. Мы же будем использовать Twig движок, по целому ряду причин.

  • Twig быстр и требует небольших ресурсов.
  • Twig лаконичен — Twig позволяет нам выполнять функции шаблонов в очень сжатом виде. Сравните это с PHP, где некоторые заявления очень многословны.
  • Twig поддерживает наследование шаблонов. Шаблоны имеют возможность расширяться и переопределять другие шаблоны, позволяют дочерним шаблонам изменять значения по умолчанию, предусмотренных родительскими шаблонами.
  • Twig безопасен – в нём по умолчанию включено экранирование и предоставляет даже из коробки среду для импортирования шаблонов.
  • Twig является расширяемым — Twig предоставляет много общей функциональности ядра, чего вы и ожидаете от движка шаблонов, но для тех случаев, когда вам нужна дополнительная функциональность, Twig может быть легко расширен.

Таковы лишь некоторые из преимуществ Twig. Другие причины почему вам рекомендуется обратить своё внимание на Twig вы можете увидеть на официальном сайте Twig.

Структура макета


Так как Twig поддерживает наследование шаблонов, мы будем использовать трёхуровневый подход наследования шаблонов. Такой подход позволяет нам изменять вид на 3-х различных уровнях приложения, давая нам большие возможности и гибкость. Почитать о шаблонах можно здесь.

Главный шаблон — Уровень 1


Начнем с создания базового шаблона для symblog. Нам понадобятся 2 файла, шаблон и CSS. Так как Symfony2 поддерживает HTML5, мы будет использовать и его. Скопируйте этот код в базовый шаблон:

<!-- app/Resources/views/base.html.twig -->
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html"; charset=utf-8" />
    <title>{% block title %}Symblog{% endblock %} - Symblog</title>
    <!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    {% block stylesheets %}
        <link href='http://fonts.googleapis.com/css?family=Irish+Grover' rel='stylesheet' type='text/css'>
        <link href='http://fonts.googleapis.com/css?family=La+Belle+Aurore' rel='stylesheet' type='text/css'>
        <link href="{{ asset('css/screen.css') }}" type="text/css" rel="stylesheet" />
    {% endblock %}
    <link rel="shortcut icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>

<section id="wrapper">
    <header id="header">
        <div class="top">
            {% block navigation %}
                <nav>
                    <ul class="navigation">
                        <li><a href="#">Home</a></li>
                        <li><a href="#">About</a></li>
                        <li><a href="#">Contact</a></li>
                    </ul>
                </nav>
            {% endblock %}
        </div>

        <hgroup>
            <h2>{% block blog_title %}<a href="#">Symblog</a>{% endblock %}</h2>
            <h3>{% block blog_tagline %}<a href="#">creating a blog in Symfony2</a>{% endblock %}</h3>
        </hgroup>
    </header>

    <section class="main-col">
        {% block body %}{% endblock %}
    </section>
    <aside class="sidebar">
        {% block sidebar %}{% endblock %}
    </aside>

    <div id="footer">
        {% block footer %}
            Symfony2 blog tutorial - created by <a href="https://github.com/dsyph3r">dsyph3r</a>
        {% endblock %}
    </div>
</section>

{% block javascripts %}{% endblock %}
</body>
</html>

Заметка

Есть 3 внешних файла, использованных в шаблоне, 1 JavaScript и 2 CSS. Файл JavaScript фиксит отсутствие поддержки HTML5 в IE браузерах до версии 9. 2 CSS файлы импортируют шрифты из веб-шрифтов Google.

Этот шаблон размечает основную структуру нашего блога. Большая часть шаблона состоит из HTML, с тегами Twig. Теги Twig, мы рассмотрим далее.

Обратим внимание на заголовок. Давайте посмотрим на название:

<title>{% block title %}Symblog{% endblock %} - Symblog</title>

Первое, что вы заметите, неизвестный {% тег. Это не HTML, и безусловно не PHP. Это один из 3 Twig тегов. Этот тег является тегом Twig который совершает какое-то действие. Он используется для выполнения операторов, таких как объявления и определения блочных элементов. Полный список можно найти в документации Twig. Twig блок который мы определили в названии делает 2 вещи; Он устанавливает идентификатор блока к заголовку, и обеспечивает отображение по умолчанию между block и endblock тегами. Определяя блок, мы можем в будущем им воспользоваться. Например, на странице для отображения постов блога мы хотели бы, чтобы в заголовке страницы выводилось название блога. Мы можем добиться этого путем расширения шаблона и переопределения заголовка блока.

{% extends '::base.html.twig' %}

{% block title %}The blog title goes here{% endblock %}

В приведенном выше примере мы расширили шаблон унаследовав базовый шаблон. Вы заметите, что в формате шаблона отсутствует части Бандл и Контроллер, помните, формат Бандл: Контроллер: Шаблон??? Исключив Бандл и Контроллер мы указали что будет использоваться шаблон на уровне приложения определённого в app/Resources/views.

Далее, мы определили еще один блок и наполним содержанием, в нашем случае это Заголовок блога. Так как родительский шаблон уже содержит Блок Заголовка, он переопределяется нашим. Сейчас выводится "The blog title goes here – symblog”. Эта функциональность обеспечивается Twig и будет широко использоваться при создании шаблонов.

В блоке Стилей мы знакомимся наследующим Twig тегом {{ или “определи что-то” тег.

<link href="{{ asset('css/screen.css') }}" type="text/css" rel="stylesheet" />

Этот тег используется для вывода значения переменной или выражения. В приведенном выше примере выводит значения, возвращаемого функцией asset, которая обеспечивает нас портативным способом, получения ссылок на assets приложений, таких как CSS, JavaScript и изображения.

Тег {{ также может быть объединен с фильтрами для манипулирования вывода перед отображением.

{{ blog.created|date("d-m-Y") }}


Для получения полного списка фильтров посмотрите документацию Twig.

Последний Twig тег, который мы не видели в шаблонах тэг комментария — {#. Его использование выглядит так:

{# The quick brown fox jumps over the lazy dog #}

Никакие другие концепции не представлены в этом шаблоне. Он обеспечивает нас основным макетом, чтобы настроить его, так как нам нужно.

Давайте добавим несколько стилей. Создайте файл таблиц стилей, web/css/screen.css и добавьте следующее содержание. Это позволит добавить стили для главного шаблона.

html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0}

body { line-height: 1;font-family: Arial, Helvetica, sans-serif;font-size: 12px; width: 100%; height: 100%; color: #000; font-size: 14px; }
.clear { clear: both; }

#wrapper { margin: 10px auto; width: 1000px; }
#wrapper a { text-decoration: none; color: #F48A00; }
#wrapper span.highlight { color: #F48A00; }

#header { border-bottom: 1px solid #ccc; margin-bottom: 20px; }
#header .top { border-bottom: 1px solid #ccc; margin-bottom: 10px; }
#header ul.navigation { list-style: none; text-align: right; }
#header .navigation li { display: inline }
#header .navigation li a { display: inline-block; padding: 10px 15px; border-left: 1px solid #ccc; }
#header h2 { font-family: 'Irish Grover', cursive; font-size: 92px; text-align: center; line-height: 110px; }
#header h2 a { color: #000; }
#header h3 { text-align: center; font-family: 'La Belle Aurore', cursive; font-size: 24px; margin-bottom: 20px; font-weight: normal; }

.main-col { width: 700px; display: inline-block; float: left; border-right: 1px solid #ccc; padding: 20px; margin-bottom: 20px; }
.sidebar { width: 239px; padding: 10px; display: inline-block; }

.main-col a { color: #F48A00; }
.main-col h1,
.main-col h2
{ line-height: 1.2em; font-size: 32px; margin-bottom: 10px; font-weight: normal; color: #F48A00; }
.main-col p { line-height: 1.5em; margin-bottom: 20px; }

#footer { border-top: 1px solid #ccc; clear: both; text-align: center; padding: 10px; color: #aaa; }


Шаблон Бандла – Уровень 2


Теперь мы перейдем к созданию макета для BlogBundle. Создайте файл, расположенный в src/Blogger/BlogBundle/Resources/views/layout.html.twig и добавьте следующее содержание.

{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{% extends '::base.html.twig' %}

{% block sidebar %}
    Sidebar content
{% endblock %}


На первый взгляд этот шаблон может показаться немного простым, но его простота и является ключом. Во-первых, расширяет базовый шаблон, который мы создали ранее. Во-вторых, переопределяет родительский sidebar. Так как sidebar будет присутствовать на всех страницах нашего блога имеет смысл выполнить настройку на этом уровне. Вы можете спросить, почему бы нам просто не поставить настройки в шаблоне приложения, так как он будет присутствовать на всех страницах. Это просто, приложение ничего не знает о Бандле и не должно. Бандл должен самостоятельно содержать всю свою функциональность и вывод sidebar’а является частью этой функциональности. Итак, почему бы нам просто не поставить sidebar в каждом из шаблонов страниц? Опять же, это просто, мы бы дублировали sidebar каждый раз, когда добавляли бы страницу. Этот шаблон второго уровня даст нам гибкость в будущем добавить другие настройки. Например, мы хотим изменить копию подвала на всех страницах, это было бы прекрасное место, чтобы сделать это.

Шаблон страницы — Уровень 3


Наконец, мы готовы для макета контроллера. Эти макеты будут широко связаны с действием контроллера, то есть blog show actionбудет иметь blog show шаблон.

Начнем с создания контроллера для домашней страницы и ее шаблона. Так как это первая страница, которую мы создаём, мы должны создать контроллер. Создайте контроллер

src/Blogger/BlogBundle/Controller/PageController.php
и добавьте следующее:

<?php
// src/Blogger/BlogBundle/Controller/PageController.php

namespace Blogger\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class PageController extends Controller
{
    public function indexAction()
    {
        return $this->render('BloggerBlogBundle:Page:index.html.twig');
    }
}


Теперь создайте шаблон для этой функции. Как вы можете видеть в функции контроллера мы будем отображать шаблон индексной страницы. Создайте шаблон:

src/Blogger/BlogBundle/Resources/views/Page/index.html.twig


{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}
{% extends 'BloggerBlogBundle::layout.html.twig' %}

{% block body %}
    Blog homepage
{% endblock %}


В этом примере BloggerBlogBundle::layout.html.twig пропущено имя контроллера. Исключив имя контроллера, мы указали использование шаблона уровня Bundle src/Blogger/BlogBundle/Resources/views/layout.html.twig.
Теперь давайте добавим маршрут для нашего сайта. Обновите файл конфигурации src/Blogger/BlogBundle/Resources/config/routing.yml:

# src/Blogger/BlogBundle/Resources/config/routing.yml
BloggerBlogBundle_homepage:
    path:     /
    defaults: { _controller: "BloggerBlogBundle:Page:index" }
    requirements:
         methods:  GET

Теперь мы готовы, чтобы посмотреть на наш шаблон Blogger. Перейдите в браузере по адресу http://localhost:8000.

Вы должны увидеть основной макет блога, с основным содержанием и sidebar’ом.



Страница “About”


Последняя задача в этой части урока будет создание статической страницы “About”. Это продемонстрирует, как связать страницы вместе, и далее применять подход трёхуровневого наследования шаблонов принятого нами.

Маршрут


При создании новой страницы, одна из первых задач состоит в создании маршрута для неё. Откройте файл маршрутизации BloggerBlogBundle расположенный в src/Blogger/BlogBundle/Resources/config/routing.ymlи добавьте следующее правило маршрутизации.

# src/Blogger/BlogBundle/Resources/config/routing.yml
BloggerBlogBundle_about:
    path:   /about
    defaults: { _controller: "BloggerBlogBundle:Page:about" }
    requirements:
         methods:  GET


Контроллер



Затем откройте Page Controller, расположенный в

src/Blogger/BlogBundle/Controller/PageController.php


и добавьте действие для обработки страницы “About”:

// src/Blogger/BlogBundle/Controller/PageController.php

class PageController extends Controller
{
    //...

    public function aboutAction()
    {
        return $this->render('BloggerBlogBundle:Page:about.html.twig');
    }

}

Отображение


Для отображения шаблона создайте новый файл src/Blogger/BlogBundle/Resources/views/Page/about.html.twig и скопируйте туда:

{# src/Blogger/BlogBundle/Resources/views/Page/about.html.twig #}
{% extends 'BloggerBlogBundle::layout.html.twig' %}

{% block title %}About{% endblock%}

{% block body %}
    <header>
        <h1>About symblog</h1>
    </header>
    <article>
        <p>Donec imperdiet ante sed diam consequat et dictum erat faucibus. Aliquam sit
            amet vehicula leo. Morbi urna dui, tempor ac posuere et, rutrum at dui.
            Curabitur neque quam, ultricies ut imperdiet id, ornare varius arcu. Ut congue
            urna sit amet tellus malesuada nec elementum risus molestie. Donec gravida
            tellus sed tortor adipiscing fringilla. Donec nulla mauris, mollis egestas
            condimentum laoreet, lacinia vel lorem. Morbi vitae justo sit amet felis
            vehicula commodo a placerat lacus. Mauris at est elit, nec vehicula urna. Duis a
            lacus nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices
            posuere cubilia Curae.</p>
    </article>
{% endblock %}


В странице “About” нет ничего особенного. Это всего лишь функция, которая выводит шаблон с некоторым контентом Она тем не менее приведёт нас к следующей задаче.

Ссылки на страницы


Теперь мы имеем страницу “About”. Перейдите по адресу http://localhost:8000/about чтобы в этом убедиться. Однако у пользователя нет никакого другого способа попасть на эту страницу кроме как написать в адресную строку полный её адрес, что мы и сделали выше. Запомните вы всегда должны использовать функции маршрутизации, предоставляемые Symfony2, никогда не используете следующее:

<a href="/contact">Contact</a>

<?php $this->redirect("/contact"); ?>

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

1. Этот подход использует жесткую ссылку, и полностью игнорирует систему маршрутизации Symfony2. Например если вы захотите изменить в любой момент расположение страницы контактов вам придется найти все ссылки на жесткой связи и изменить их.
2. Он будет игнорировать среду контроллеров. Среды являются тем, что мы на самом деле не объяснили, но вы их уже использовали. App_dev.php — фронт-контроллер обеспечивает нам доступ к нашему приложению в среде Dev. Если вы замените app_dev.php на app.php, вы будете запускать приложение в среде Prod. Значимость этих условий будет объяснено далее в уроке, но сейчас важно отметить, что жесткая ссылка не поддерживает текущую среду где мы находимся.

Правильный способ связать страницы это path и url — методы, предусмотренные Twig. Они оба очень похожи, метод URL будет предоставлять нам абсолютный URL. Давайте обновим шаблон приложения app/Resources/views/base.html.twig и свяжем Домашнюю страницу со страницей “About” вместе.

<!-- app/Resources/views/base.html.twig -->
{% block navigation %}
    <nav>
        <ul class="navigation">
            <li><a href="{{ path('BloggerBlogBundle_homepage') }}">Home</a></li>
            <li><a href="{{ path('BloggerBlogBundle_about') }}">About</a></li>
            <li><a href="#">Contact</a></li>
        </ul>
    </nav>
{% endblock %}


Теперь обновите страницу, вы увидите, что ссылки на страницы работают.

Наконец обновим ссылки логотипа, которые перенаправят вас на главную страницу. Обновите шаблон, расположенный app/Resources/views/base.html.twig.

<!-- app/Resources/views/base.html.twig -->
<hgroup>
    <h2>{% block blog_title %}<a href="{{ path('BloggerBlogBundle_homepage') }}">symblog</a>{% endblock %}</h2>
    <h3>{% block blog_tagline %}<a href="{{ path('BloggerBlogBundle_homepage') }}">creating a blog in Symfony2</a>{% endblock %}</h3>
</hgroup>

Заключение


Мы начали исследовать фундаментальные концепции, лежащие в приложении Symfony2, в том числе маршрутизацию и движок шаблонов Twig.

В следующей части мы создадим страницу контактов. Эта страница немного сложнее, чем страница «About», и позволяет пользователям взаимодействовать с веб-формой, чтобы отправлять нам запросы. В следующей части мы введём новые понятия и узнаем, что такое Валидатор форм в Symfony2.

Источники и вспомогательные материалы:

https://symfony.com/
http://tutorial.symblog.co.uk/
http://twig.sensiolabs.org/
http://www.doctrine-project.org/

Post Scriptum
Всем спасибо за внимание, если у вас возникли сложности или вопросы, отписывайтесь в комментарии или личные сообщения, добавляйтесь в друзья.


Часть 2 — Страница с контактной информацией: валидаторы, формы и электронная почта
Поделиться с друзьями
-->

Комментарии (38)


  1. maximkou
    25.05.2016 18:16

    Неплохое руководство, продолжайте свое начинание.


  1. maximkou
    25.05.2016 18:19
    +1

    Единственное, что бы хотелось вам предложить — руководство добавить в репозиторий, так сказать разбираться не отходя от кассы. И еще исключать файлы IDE из репозитория (папка .idea в вашем случае)


    1. antoscenco-vladimir
      25.05.2016 21:00

      Учту обязательно ) Спасибо за комментарий


  1. shot131
    25.05.2016 19:52

    Почему не используете аннотации для роутинга? Вроде в best practices советуют использовать именно их. Интересно чем обусловлен такой выбор, сам я в symfony не силён.


    1. VanSanblch
      25.05.2016 20:17

      Было видео на Youtube, ссылку, к сожалению, не могу найти, в котором говорилось что «best practices» написано с прицелом на начинающих разработчиков, что бы не грузить их академичностью подхода фреймворка.

      В тех же практиках рекомендуется использовать YAML для задания сервисов, мол, так проще читать и в дальнейшем поддерживать. Однако более продвинутый подход предполагает всё таки XML для этих целей. Как минимум потому что благодаря IDE можно проверять корректность и валидность документа.


      1. lowadka
        25.05.2016 20:56

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


      1. hudson
        25.05.2016 20:58

        А не можете ссылочкой поделиться? У меня от Best practices примерно такие же ощущения остались…


        1. bogomya
          26.05.2016 15:42
          +1

          Наверное вот этот доклад от Олега Зинченко
          www.youtube.com/watch?v=Fu9j7w2hbW8


          1. hudson
            26.05.2016 16:36

            Спасибо!


      1. Nidhognit
        26.05.2016 09:52

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

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


    1. antoscenco-vladimir
      25.05.2016 21:02

      Выбор не мой, а автора оригинального руководства это всего лишь перевод с некоторыми дополнениями


  1. M-A-XG
    25.05.2016 21:25
    -5

    1. Спасибо за ликбез
    2. Симфони один из наиболее сложных фреймворков, местами логичность страдает
    3. Как он в сравнение с Ларавель?
    4. Фреймворки в общем-то фигня: http://blog.kpitv.net/article/frameworks-1/


    1. greowe
      25.05.2016 23:08
      +4

      4. имо, не с таким сайтом писать такие утверждения:)


      1. larion_turlo
        26.05.2016 11:38

        Вполне себе в стиле веб-брутализм


      1. M-A-XG
        26.05.2016 17:39

        1. А чем Вам тот сайт не нравится? :)
        2. Какая корелляция между внешним видом и фреймворком?


    1. Assada
      26.05.2016 10:21
      +1

      Внимание! Товарищи! Не открывайте ссылку из 4го пункта! Там еще тот адок. Берегите ваши стулья.


      1. antoscenco-vladimir
        26.05.2016 11:41

        Расшифруйте пожалуйста Ваш комментарий )


        1. oxidmod
          26.05.2016 12:02

          гражданина, ты туда не ходи
          http://blog.kpitv.net/article/frameworks-1/


          1. antoscenco-vladimir
            26.05.2016 12:10

            Сколько людей, столько и мнений )


            1. SerafimArts
              26.05.2016 12:21

              TL;DR статьи по ссылке: "т.к. в Yii это сделано через одно место, значит все фреймворки уг."


              1. M-A-XG
                26.05.2016 17:30

                В других тоже не все сделано хорошо :)


  1. hiwibu
    25.05.2016 23:08
    +1

    Спасибо огромное. По симфони очень мало обучающих материалов на руссском языке для новичков, а тут такой подарок. Все понятно и доходчиво.
    Подписался. Жду следующих уроков.


  1. zmeykas
    25.05.2016 23:17

    Недавно заинтересовался знакомством с Symfony, но планировал ориентироваться уже на Symfony 3. А по какой причине вы для руководства выбрали 2.8 и насколько это руководство актуально для третей версии?


    1. antoscenco-vladimir
      26.05.2016 00:04

      выбрал из-за приставки LTS, думаю что некоторые моменты в следующих статьях для третьей версии актуальны не будут


    1. SerafimArts
      26.05.2016 00:23

      Если грубо, то 2.8 от 3.0 не отличается ничем, кроме минимальной требуемой версии пыха.


      1. Big_Shark
        26.05.2016 02:47
        +1

        Ну они еще все деприкейтед удалили из симфони, так что если сразу писать нормальный код, то разницу и не заметишь.


  1. Jenly
    25.05.2016 23:54
    -1

    Вы вообще осознаете, что перевели статью 4 летней давности?


    1. antoscenco-vladimir
      25.05.2016 23:59

      на русском языке я ее не встречал или в чем суть вашего вопроса?


      1. antoo
        26.05.2016 02:05

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

        Я не разрабатывал на Symfony и мне интересно, неужели там за столько времени ничего не поменялось? Статья рассчитана на новичков, даже если и приведённый код работает — актуальны ли используемые подходы сегодня, чтобы начинающие учились делать так же?


        1. antoscenco-vladimir
          26.05.2016 07:47
          +2

          статья взята за основу, а документацией пользуюсь для версии 2.8.1, чтобы код работал под эту версию, поэтому думаю, что в целом информация актуальна


          1. IncorrecTSW
            26.05.2016 09:36

            Только не хватает phpdoc'a, роутинг все же как выше писали лучше через аннотации и шаблоны к слову в «ваших» примерах, тоже лучше через них. Да и все же какой год на дворе, добавить бы возвращаемые значения. На текущий момент, как по мне, пример крайне среднего качества.


            1. antoscenco-vladimir
              26.05.2016 10:07

              Автор оригинальной статьи сделал так как посчитал нужным, я всего лишь стараюсь перевести и сделать так чтобы это работало под версию 2.8.1, когда будут переводы всех разделов вы можете исправить все недочёты и опубликовать ваше видение или посмотреть следующий раздел оригинальной статьи и присоединиться к переводу, чтобы сделать материал более актуальным и лучше, лично я буду Вам за это только благодарен, чем больше людей будут участвовать тем лучше Спасибо за комментарий


              1. IncorrecTSW
                26.05.2016 11:39

                Мне видится вариант не столько перевода сколько пересказ на свой лад, с актуализированными примерами на гите. Присоединиться был бы не против, если возьмете.


                1. antoscenco-vladimir
                  26.05.2016 11:57

                  Отписался в личку


  1. antoscenco-vladimir
    27.05.2016 16:40

    Lev_Max у меня нет возможность написать Вам в личку из-за ограничений Вашего аккаунта, спасибо за замечание, следующий раздел уже переведен и выйдет в ближайшие дни


    1. antoscenco-vladimir
      27.05.2016 17:02

      возможности *


  1. zhigalin
    27.05.2016 20:24

    Ммм, почему вы используете Гитхаб как рапидшару какую-то?


    1. antoscenco-vladimir
      02.06.2016 05:21

      мне так удобнее, если будет какое-то исправление то на ту же «рапидшару» придётся каждую часть перезаливать, а в Github можно смержить