<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>hudson@work &#187; bird’s eye view</title>
	<atom:link href="http://hudson.su/tag/birds-eye-view/feed/" rel="self" type="application/rss+xml" />
	<link>http://hudson.su</link>
	<description>статьи о web-разработке, менеджменте IT проектов и контроле качества</description>
	<lastBuildDate>Fri, 20 Jan 2012 13:15:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Symfony 2.0 – быстрый тур – архитектура/the architecture (часть 5)</title>
		<link>http://hudson.su/2010/04/04/symfony-2-0-quick-tour-part-5/</link>
		<comments>http://hudson.su/2010/04/04/symfony-2-0-quick-tour-part-5/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 17:08:55 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[bird’s eye view]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Symfony2 quick tour]]></category>
		<category><![CDATA[web разработка]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1321</guid>
		<description><![CDATA[Symfony 2.0 – быстрый тур – общая картинка (часть 1) Symfony 2.0 – быстрый тур – вид/the view (часть 2) Symfony 2.0 – быстрый тур – контроллер/the controller (часть 3) Symfony 2.0 – быстрый тур – пакеты/the bundles (часть 4) Первые 4 части этого руководства позволили составить обще представление о Symfony 2.0. Но они не [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://hudson.su/?p=1032" target="_blank">Symfony 2.0 – быстрый тур – общая картинка (часть 1)</a></li>
<li><a href="http://hudson.su/?p=1094" target="_blank">Symfony 2.0 – быстрый тур – вид/the view (часть 2)</a></li>
<li><a href="http://hudson.su/?p=1174" target="_blank">Symfony 2.0 – быстрый тур – контроллер/the controller (часть 3)</a></li>
<li><a href="http://hudson.su/?p=1235" target="_blank">Symfony  2.0 – быстрый тур – пакеты/the bundles  (часть  4)</a></li>
</ul>
<p>Первые 4 части этого руководства позволили составить обще представление о Symfony 2.0. Но они не останавливаются на структуре директорий проекта. Поскольку это одна из отличительных особенностей Symfony, давайте-ка остановимся на этом подробнее.</p>
<p><span id="more-1321"></span>Структура директорий приложения Symfony очень гибкая. Это руководство описывает рекомендуемую структуру, но, как вы скоро поймете, все можно изменять.</p>
<h2>Структура директорий / The Directory Structure</h2>
<p>Структура директорий песочницы отражает типовую и рекомендованную структуру приложения Symfony:</p>
<ul>
<li><code>hello/</code>: Эта директория, названная по имени вашего приложения, содержит конфигурационные файлы;</li>
<li><code>src/</code>: Весь PHP код находится в этой директории;</li>
<li><code>web/</code>: Это директория web root.</li>
</ul>
<h3>Директория web / The Web Directory</h3>
<p>Корень веб &#8211; это домашняя директория для всех публичных и статических файлов типа изображений, стилей и javascript-файлов. Она также содержит боевой фронт-контроллер:</p>
<pre># web/index.php
&lt;?php

require_once __DIR__.'/../hello/HelloKernel.php';

$kernel = new HelloKernel('prod', false);
$kernel-&gt;run();</pre>
<p>Как и любой другой фронт-контроллер, <code>index.php</code> использует Kernel  Class, <code>HelloKernel</code>, для инициализации и запуска приложения.</p>
<h3>Директория приложения / The Application Directory</h3>
<p><code>Класс </code><code>HelloKernel</code> это главная точка входа  в настройки приложения и он хранится в директории <code>hello/</code>.</p>
<p>Этот класс должен реализовывать 5 методов:</p>
<ul>
<li><code>registerRootDir()</code>: Возвращает корневую директорию;</li>
<li><code>registerBundles()</code>: Возвращает массив всех пакетов (бандлов) нобходимых для запуска приложения (обратите внимание на <code>ApplicationHelloBundleBundle</code>);</li>
<li><code>registerBundleDirs()</code>: Возвращает массив ассоциаций пространств имен и их домашних директорий;</li>
<li><code>registerContainerConfiguration()</code>: Возвращает главный конфигурационный объект (об этом подробнее ниже);</li>
<li><code>registerRoutes()</code>: Возвращает конфигурацию маршрутизатора.</li>
</ul>
<p>Обратите внимание на дефолтную реализацию этих методов для того чтобы лучше понять гибкость фреймворка. В начале этого руководства вы открывали файл <code>hello/config/routing.yml</code>. Этот путь был сконфигурирован в методе <code>registerRoutes()</code>:</p>
<pre>public function registerRoutes()
{
  $loader = new RoutingLoader($this-&gt;getBundleDirs());

  return $loader-&gt;load(__DIR__.'/config/routing.yml');
}</pre>
<p>Также в этом месте вы можете переключиться между использованием конфигурационных файлов в YAML формате на XML или плоский PHP код, если вам так будет удобнее.</p>
<p>Для того чтобы это все работало, ядро подключает два файла из директории <code>src/</code>:</p>
<pre># hello/HelloKernel.php
require_once __DIR__.'/../src/autoload.php';
require_once __DIR__.'/../src/vendor/symfony/src/Symfony/Foundation/bootstrap.php';</pre>
<h3>Директория исходных кодов / The Source Directory</h3>
<p>Файл <code>src/autoload.php</code> отвечает за автозагрузку всех файлов из директории <code>src/</code>:</p>
<pre># src/autoload.php
require_once __DIR__.'/vendor/symfony/src/Symfony/Foundation/UniversalClassLoader.php';

use SymfonyFoundationUniversalClassLoader;

$loader = new UniversalClassLoader();
$loader-&gt;registerNamespaces(array(
  'Symfony'     =&gt; __DIR__.'/vendor/symfony/src',
  'Application' =&gt; __DIR__,
  'Bundle'      =&gt; __DIR__,
  'Doctrine'    =&gt; __DIR__.'/vendor/doctrine/lib',
));
$loader-&gt;registerPrefixes(array(
  'Swift_' =&gt; __DIR__.'/vendor/swiftmailer/lib/classes',
  'Zend_'  =&gt; __DIR__.'/vendor/zend/library',
));
$loader-&gt;register();

// for Zend Framework &amp; SwiftMailer
set_include_path(__DIR__.'/vendor/zend/library'.PATH_SEPARATOR.__DIR__.'/vendor/swiftmailer/lib'.PATH_SEPARATOR.get_include_path());</pre>
<p>Класс <code>UniversalClassLoader</code> используется для автозагрузки файлов, которые удовлетворяют либо техническому стандарту для пространств имен в PHP 5.3 или же соглашению о наименовании классов PEAR. Как вы можете видеть, все зависимости хранятся в директории <code>vendor/</code>, но, это всего-лишь соглашение. Вы можете хранить их где вам удобно, глобально на сервере или локально в вашем проекте.</p>
<h2>Еще немного о пакетах / More about Bundles</h2>
<p>Как мы могли видеть в предыдущей части, приложение состоит из пакетов, определенных в методе <code>registerBundles()</code>:</p>
<pre># hello/HelloKernel.php
public function registerBundles()
{
  return array(
    new SymfonyFoundationBundleKernelBundle(),
    new SymfonyFrameworkWebBundleBundle(),
    new SymfonyFrameworkDoctrineBundleBundle(),
    new SymfonyFrameworkSwiftmailerBundleBundle(),
    new SymfonyFrameworkZendBundleBundle(),
    new ApplicationHelloBundleBundle(),
  );
}</pre>
<p>Но как же Symfony понимает где искать пакеты? Symfony очень гибок в этом отношении. Метод <code>registerBundleDirs()</code> должен возвращать ассоциативный массив, который ставит в соответствие пространству имен некоторую валидную директорию (локальную или глобальную):</p>
<pre>public function registerBundleDirs()
{
  return array(
    'Application'        =&gt; __DIR__.'/../src/Application',
    'Bundle'             =&gt; __DIR__.'/../src/Bundle',
    'Symfony\Framework' =&gt; __DIR__.'/../src/vendor/symfony/src/Symfony/Framework',
  );
}</pre>
<p>Итак, когда вы ссылаетесь на <code>HelloBundle</code> в имени контроллера или в имени шаблона, Symfony будет искать его в указанных директориях.</p>
<p>Ну как, вы поняли почему Symfony такой гибкий? Используйте ваши пакеты в различных приложениях, храните их локально или глобально на ваш выбор.</p>
<h2>Вендоры / Vendors</h2>
<p>Часто ваше приложение будет зависеть от сторонних библиотек. Они должны храниться в директории <code>src/vendor/</code>. Она уже содержит библиотеки Symfony &#8211; SwiftMailer, Doctrine ORM, и избранное из классов Zend Framework.</p>
<h2>Кэш и логи / Cache and Logs</h2>
<p>Symfony это один из самых быстрых фреймворков. Но как он может быть таким быстрым, если он постоянно должен парсить и интерпретировать десятки YAML и XML файлов? Частично это обязанность системы кеширования. Конфигурация приложения парсится только для первого запроса и после этого компилируется в обычный PHP код, который хранится в директории приложения <code>cache/</code>. В девелоперском окружении Symfony сбрасывает кэш когда вы изменяете файл, но в продуктовом окружении это уже ваша обязанность чистить кэш, когда вы обновляете ваш код или конфигурацию.</p>
<p>Во время разработки web-приложения что-то может пойти не так в любой момент. Файлы логов в директории приложения <code>logs/</code> могут рассказать вам подробности о запросах и помочь разобраться в проблеме, не затратив много времени.</p>
<h2>Интерфейс командной строки / The Command Line Interface</h2>
<p>Каждое приложение идет комплекте с инструментом командной строки (консоль), который помогает обслуживать приложение. Консоль предоставляет команды, которые увеличивают вашу продуктивность, автоматизируя часты и повторяющиеся задачи.</p>
<p>Запустите консоль без агрументов, для того чтобы получить представление о ее возможностях:</p>
<pre>$ php hello/console</pre>
<p>Опция <code>--help</code> поможет вам уточнить способ использования любой команды:</p>
<pre>$ php hello/console router:debug --help</pre>
<h2>Последний рывок / Final Thoughts</h2>
<p>Назовите меня чокнутым, но после прочтения этой части, вы должны уметь заставить работать Symfony на вас быстро и комфортно. Так что, перемещайте директории как вам угодно, не стесняйтесь.</p>
<p>Вы уже всего лишь в шаге от того чтобы стать мастером Symfony. Это действительно так, после прочтения следующей главы о том, как расширять фреймворк, вы сможете разрабатывать востребованные приложения с Symfony.</p>
<blockquote><p>Источник: <a href="http://symfony-reloaded.org/quick-tour-part-5" target="_blank">http://symfony-reloaded.org/quick-tour-part-5</a></p>
<p>P.S. На текущий момент, увы, на официальном сайте проекта следующей главы, на которую ссылается автор, пока нет. Так что пока повременим становиться мастерами симфонии (ваш hudson).</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/04/04/symfony-2-0-quick-tour-part-5/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Symfony 2.0 – быстрый тур – пакеты/the bundles (часть 4)</title>
		<link>http://hudson.su/2010/03/31/symfony-2-0-quick-tour-part-4/</link>
		<comments>http://hudson.su/2010/03/31/symfony-2-0-quick-tour-part-4/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 17:32:10 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[bird’s eye view]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Symfony2 quick tour]]></category>
		<category><![CDATA[web разработка]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1235</guid>
		<description><![CDATA[А вот и вы, мой герой ) Ну кто бы мог подумать, что вы все еще будете с нами после первых трех частей ) Однако же, ваши усилия скоро будут щедро вознаграждены. В этой части мы коснемся пожалуй самой мощной функции Symfony &#8211; системы пакетов (bundles). Symfony 2.0 – быстрый тур – общая картинка (часть [...]]]></description>
			<content:encoded><![CDATA[<p>А вот и вы, мой герой ) Ну кто бы мог подумать, что вы все еще будете с нами после первых трех частей ) Однако же, ваши усилия скоро будут щедро вознаграждены. В этой части мы коснемся пожалуй самой мощной функции Symfony &#8211; системы пакетов (bundles).</p>
<p><span id="more-1235"></span></p>
<ul>
<li><a href="http://hudson.su/?p=1032" target="_blank">Symfony 2.0 – быстрый тур – общая картинка (часть 1)</a></li>
<li><a href="http://hudson.su/?p=1094" target="_blank">Symfony 2.0 – быстрый тур – вид/the view (часть 2)</a></li>
<li><a href="http://hudson.su/?p=1174" target="_blank">Symfony 2.0 – быстрый тур – контроллер/the controller (часть 3)</a></li>
<li><a href="http://hudson.su/?p=1321" target="_blank">Symfony 2.0 – быстрый тур – архитектура/the architecture (часть 5)</a></li>
</ul>
<h2>Система пакетов / The Bundle System</h2>
<p>Пакеты в Symfony можно сравнить с модулями расширений (плагинами) в прочем программном обеспечении. Но почему же тогда мы <span style="text-decoration: line-through">кошку называем кошкой</span> пакет называем пакетом а не плагином? А потому что в Symfony все есть пакет: начиная от ядра фремворка и заканчивая кодом, который вы пишите для своего приложения. Пакеты &#8211; это граждане первейшего сорта. Они дают вам гибкость в использовании возможностей сторонних пакетов или же распространении своих собственных пакетов. Т.о. вы можете легко выбирать какие возможности будут доступны вашему приложению и оптимизировать его требуемым вам способом.</p>
<p>Приложение состоит из пакетов, определенных в методе <code>registerBundles()</code> класса <code>HelloKernel</code>:</p>
<pre># hello/HelloKernel.php
public function registerBundles()
{
  return array(
    new SymfonyFoundationBundleKernelBundle(),
    new SymfonyFrameworkWebBundleBundle(),
    new SymfonyFrameworkDoctrineBundleBundle(),
    new SymfonyFrameworkSwiftmailerBundleBundle(),
    new SymfonyFrameworkZendBundleBundle(),
    new ApplicationHelloBundleBundle(),
  );
}</pre>
<p>Обратите внимание, что наряду с <code>HelloBundle</code>, ядро подключает <code>KernelBundle</code>, <code>WebBundle</code>, <code>DoctrineBundle</code>, <code>SwiftmailerBundle </code>и <code>ZendBundle</code>. Все эти пакеты являются частью ядра фреймворка.</p>
<p>Каждый пакет может быть настроен через конфигурационные файлы, написанные на YAML или XML. Давайте взглянем на конфигурацию по-умолчанию:</p>
<pre># hello/config/config.yml
kernel.config: ~
web.web: ~
web.templating: ~</pre>
<p>Каждый параметр, например kernel.config определяет конфигурацию пакета. Некоторые пакеты могут иметь много настроек если вы используете много возможностей, например <code>WebBundle</code> имеет две настройки: <code>web.web</code> и <code>web.templating</code>.</p>
<p>Каждое окружение может переопределять конфигурацию по-умолчанию через отдельные конфигурационные файлы:</p>
<pre># hello/config/config_dev.yml
imports:
  - { resource: config.yml }

web.debug:
  exception: %kernel.debug%
  toolbar:   %kernel.debug%

zend.logger:
  priority: info
  path:     %kernel.root_dir%/logs/%kernel.environment%.log</pre>
<p>Теперь вы знаете как подключать пакеты и как конфигурировать их. Давайте теперь посмотрим что для нас могут сделать встроенные пакеты.</p>
<h2>Пользователь / The User</h2>
<p>Не смотря на то что протокол HTTP не сохраняет состояния между запросами, Symfony предоставляет отличный объект user, который представляет клиента (будь то реальный человек через интернет-обозреватель, бот или же вебсервис). Между двумя запросами Symfony сохраняет атрибуты в cookie с использованием нативных сессий PHP.</p>
<p>Эта возможность предоставляется <code>WebBundle</code> и может быть подключена при помощи следующей строки в <code>config.yml</code>:</p>
<pre># hello/config/config.yml
web:user: ~</pre>
<p>Сохранение и получение информации о пользователе осуществляется следующим образом:</p>
<pre>// store an attribute for reuse during a later user request
$this-&gt;getUser()-&gt;setAttribute('foo', 'bar');

// in another controller for another request
$this-&gt;getUser()-&gt;getAttribute('foo');

// get/set the user culture
$this-&gt;getUser()-&gt;setCulture('fr');</pre>
<p>Вы также можете хранить небольшие сообщения, которые будут доступны только для следующего запроса:</p>
<pre>$this-&gt;getUser()-&gt;setFlash('notice', 'Congratulations, your action succeeded!')</pre>
<h2>Работа с БД / Accessing the Database</h2>
<p>Если ваш проект взаимодействует с базой данных тем или иным образом, вы свободны в выборе любого удобного вам инструмента. Вы можете использовать ORM, например Doctrine или Propel, если хотите высокого уровня абстракции от БД. Но в этой секции мы не будем усложнять примеры и воспользуемся Doctrine DBAL, который представляет собой &#8220;тонкий слой&#8221; поверх PDO, для подключения к базе данных.</p>
<p>Подключим DoctrineBundle и сконфигурируем наше подключение в config.yml:</p>
<pre># hello/config/config.yml
doctrine.dbal:
  driver:   PDOMySql # can be any of OCI8, PDOMsSql, PDOMySql, PDOOracle, PDOPgSql, or PDOSqlite
  dbname:   your_db_name
  user:     root
  password: your_password # or null if there is none</pre>
<p>Вот и все. Теперь вы можете использовать объект соединения для взаимодействия с БД из любого действия:</p>
<pre>public function showAction($id)
{
  $stmt = $this-&gt;getDatabaseConnection()-&gt;execute('SELECT * FROM product WHERE id = ?', array($id));

  if (!$product = $stmt-&gt;fetch())
  {
    throw new NotFoundHttpException('The product does not exist.');
  }

  return $this-&gt;render(...);
}</pre>
<p>Выражение <code>$this-&gt;getDatabaseConnection()</code> возвращает объект, с которым можно работать как и с PDO.</p>
<h2>Отправка email / Sending Emails</h2>
<p>Отправить email в Symfony также просто как и щелкнуть пальцами. Во-первых, нужно подключить <code>SwiftmailerBundle</code> и сконфигурировать его:</p>
<pre># hello/config/config.yml
swift.mailer:
  transport: gmail # can be any of smtp, mail, sendmail, or gmail
  username:  your_gmail_username
  password:  your_gmail_password</pre>
<p>После этого вы можете использовать мэйлер в любом действии:</p>
<pre>public function indexAction($name)
{
  // get the mailer first (mandatory to initialize Swift Mailer)
  $mailer = $this-&gt;getMailer();

  $message = Swift_Message::newInstance()
    -&gt;setSubject('Hello Email')
    -&gt;setFrom('send@example.com')
    -&gt;setTo('recipient@example.com')
    -&gt;setBody($this-&gt;renderView('HelloBundle:Hello:email', array('name' =&gt; $name)))
  ;
  $mailer-&gt;send($message);

  return $this-&gt;render(...);
}</pre>
<p>Тело письма хранится в шаблоне, который рендерится при помощи метода <code>renderView()</code>.</p>
<h2>Последний рывок / Final Thoughts</h2>
<p>В этой части мы рассмотрели основные особенности Symfony. Играйтесь с Symfony, разрабатывайте небольшие приложения и, когда почувствуете себя готовыми, завершите наш небольшой тур по Symfony чтением следующей части, где мы поговорим немного более подробно о том как Symfony работает и как его можно настроить под свои нужды.</p>
<blockquote><p>Оригинал: <a href="http://symfony-reloaded.org/quick-tour-part-4" target="_blank">http://symfony-reloaded.org/quick-tour-part-4</a></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/03/31/symfony-2-0-quick-tour-part-4/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Symfony 2.0 – быстрый тур – контроллер/the controller (часть 3)</title>
		<link>http://hudson.su/2010/03/18/symfony-2-0-quick-tour-part-3/</link>
		<comments>http://hudson.su/2010/03/18/symfony-2-0-quick-tour-part-3/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 06:01:33 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[bird’s eye view]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Symfony2 quick tour]]></category>
		<category><![CDATA[web разработка]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1174</guid>
		<description><![CDATA[Вы все еще с нами после первых двух частей? Да вы уже ярый приверженец Symfony )) Давайте же без лишней суеты в третьей части разберем, что же для вас может сделать контроллер. Symfony 2.0 – быстрый тур – общая картинка (часть 1) Symfony 2.0 – быстрый тур – вид/the view (часть 2) Symfony 2.0 – [...]]]></description>
			<content:encoded><![CDATA[<p>Вы все еще с нами после первых двух частей? Да вы уже ярый приверженец Symfony )) Давайте же без лишней суеты в третьей части разберем, что же для вас может сделать контроллер.</p>
<p><span id="more-1174"></span></p>
<ul>
<li><a href="http://hudson.su/?p=1032" target="_blank">Symfony 2.0 – быстрый тур – общая картинка (часть 1)</a></li>
<li><a href="http://hudson.su/?p=1094" target="_blank">Symfony 2.0 – быстрый тур – вид/the view (часть 2)</a></li>
<li><a href="http://hudson.su/?p=1235" target="_blank">Symfony  2.0 – быстрый тур – пакеты/the bundles  (часть  4)</a></li>
<li><a href="http://hudson.su/?p=1321" target="_blank">Symfony 2.0 – быстрый тур – архитектура/the architecture (часть 5)</a></li>
</ul>
<h2>Форматы / Formats</h2>
<p>Современное web-приложение должно доставлять пользователю больше чем просто HTML-страницы. Тип контента может варьироваться от XML для RSS ил web-сервисов до JSON для Ajax-запросов. Есть множество различных форматов на любой вкус и случай жизни. Symfony имеет встроенную поддержку этих форматов. Отредактируйте <code>routing.yml</code> и добавьте <code>_format</code> создначением xml:</p>
<pre># src/Application/HelloBundle/Resources/config/routing.yml
hello:
  pattern:  /hello/:name
  defaults: { _bundle: HelloBundle, _controller: Hello, _action: index, _format: xml }</pre>
<p>Затем, добавьте шаблон <code>index.xml.php</code> рядом с <code>index.php</code>:</p>
<pre># src/Application/HelloBundle/Resources/views/Hello/index.xml.php
&lt;hello&gt;
  &lt;name&gt;&lt;?php echo $name ?&gt;&lt;/name&gt;
&lt;/hello&gt;</pre>
<p>Вот и все что нужно сделать. Не требуется даже менять контроллер. Для стандартных форматов Symfony автоматически выберет лучший заголовок <code>content-type</code> для ответа. Если вы хотите поддерживать различные форматы в одном действии (action), используйте <code>:_format</code> в настройке маршрута:</p>
<pre># src/Application/HelloBundle/Resources/config/routing.yml
hello:
  pattern:      /hello/:name.:_format
  defaults:     { _bundle: HelloBundle, _controller: Hello, _action: index, _format: html }
  requirements: { _format: (html|xml|json) }</pre>
<p>Контроллер теперь будет вызываться для URL вида: <code>/hello/Fabien.xml</code> или для <code>/hello/Fabien.json</code>. В качестве значения по умолчанию для <code>_format</code> используется html, <code>/hello/Fabien</code> и <code>/hello/Fabien.html</code> оба используют HTML формат.</p>
<p>Требования (<code>requirements</code>) определяют регулярное выражение, которому переменная для подстановки (placeholder) должна соответствовать. В этом примере, если вы захотите вызвать <code>/hello/Fabien.js</code> вы получите ошибку HTTP 404, так как запрос не соответствует требованиям маршрута.</p>
<h2>Объект ответа / The Response Object</h2>
<p>Давайте теперь вернемся к контроллеру Hello:</p>
<pre>public function indexAction($name)
{
  return $this-&gt;render('HelloBundle:Hello:index', array('name' =&gt; $name));
}</pre>
<p>Метод render() осуществляет отображение шаблона и возвращает объект Response. Ответ сервера может быть донастроен перед его отправкой клиенту, например, можно изменить Content-type:</p>
<pre>public function indexAction($name)
{
  $response = $this-&gt;render('HelloBundle:Hello:index', array('name' =&gt; $name));
  $response-&gt;setHeader('Content-Type', 'text/plain');

  return $response;
}</pre>
<p>Для простейших шаблонов вы даже можете создавать объект Response вручную и сэкономить этим несколько милисекунд:</p>
<pre>public function indexAction($name)
{
  return $this-&gt;createResponse('Hello '.$name);
}</pre>
<p>Чаще всего это имеет смыл применять, например, для JSON-содержимого, что, в свою очередь, может быть использовано для Ajax-запросов.</p>
<h2>Управление ошибками / Error Management</h2>
<p>Когда что-то не может быть найдено, вы должны вернуть ошибку 404. Это легко сделать, вызвав специальное HTTP исключение:</p>
<pre>use SymfonyComponentsRequestHandlerExceptionNotFoundHttpException;

public function indexAction()
{
  $product = // retrieve the object from database
  if (!$product)
  {
    throw new NotFoundHttpException('The product does not exist.');
  }

  return $this-&gt;render(...);
}</pre>
<p><code>NotFoundHttpException</code> вернет в браузер ответ с ошибкой 404. Похожим образом действует и исключение <code>ForbiddenHttpException</code>, которое возвращает ошибку 403 и <code>UnauthorizedHttpException</code>, которое возвращает ошибку 401. Для других кодов ошибок вы можете использовать базовый класс  <code>HttpException</code> и передавать код ошибки в качестве кода исключения:</p>
<pre>throw new HttpException('Unauthorized access.', 401);</pre>
<h2>Перемещения и перенаправления / Redirecting and Forwarding</h2>
<p>Если вы хотите переместить пользователя на другую страницу, вы можете использовать метод redirect().</p>
<pre>$this-&gt;redirect($this-&gt;generateUrl('hello', array('name' =&gt; 'Lucas')));</pre>
<p>Метод generateUrl здесь &#8211; это такой же метод, как и generate(), который мы использовали в хелпере маршрутизации ранее. Он принимает в качестве аргументов наименование маршрутов и массив параметров, на основе чего возвращает дружественный URL. Вы также легко можете перенаправить одно действие на другое при помощи метода forward(). Как и хелпер $view-actions, он выполняет внутренний подзапрос, но он возвращает объект  Response, который при необходимости можно изменять:</p>
<pre>$response = $this-&gt;forward('HelloBundle:Hello:fancy', array('name' =&gt; $name, 'color' =&gt; 'green'));

// do something with the response or return it directly</pre>
<h2>Объект запроса / The Request Object</h2>
<p>Кроме значений подстановки (placeholders) из маршрутов, контроллер также имеет доступ к объекту запроса Request:</p>
<pre>$request = $this-&gt;getRequest();

$request-&gt;isXmlHttpRequest(); // is it an Ajax request?

$request-&gt;getPreferredLanguage(array('en', 'fr'));

$request-&gt;getQueryParameter('page'); // get a $_GET parameter

$request-&gt;getRequestParameter('page'); // get a $_POST parameter</pre>
<p>В шаблоне вы также можете получить доступ к объекту запроса через хелпер request:</p>
<pre>&lt;?php echo $view-&gt;request-&gt;getParameter('page') ?&gt;</pre>
<h2>Последний рывок / Final Thoughts</h2>
<p>Вот и все, что хотелось рассказать, и я  даже не уверен, что мы использовали все 10 минут )) В предыдущей части мы  видели, как можно расширить систему шаблонов при помощи хелперов. Расширение возможностей контроллеров может быть легко достигнуто благодаря пакетам (bundles). Но это уже тема для нашего следующего разговора!</p>
<blockquote><p>Оригинал: <a href="http://symfony-reloaded.org/quick-tour-part-3" target="_blank">http://symfony-reloaded.org/quick-tour-part-3</a></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/03/18/symfony-2-0-quick-tour-part-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Symfony 2.0 &#8211; быстрый тур &#8211; вид/the view (часть 2)</title>
		<link>http://hudson.su/2010/03/12/symfony-2-0-quick-tour-part-2/</link>
		<comments>http://hudson.su/2010/03/12/symfony-2-0-quick-tour-part-2/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 06:17:06 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[bird’s eye view]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Symfony2 quick tour]]></category>
		<category><![CDATA[web разработка]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1094</guid>
		<description><![CDATA[Вы решили что после прочтения первой части, что стоит потратить на Symfony еще 10 минут? Отлично! Во второй части мы узнаем у системе шаблонов в Symfony. Как вы могли видеть ранее, Symfony использует PHP в качестве шаблонного движка по-умолчанию, добавляет несколько отличных возможностей, что делает его более мощным. Symfony 2.0 – быстрый тур – общая [...]]]></description>
			<content:encoded><![CDATA[<p>Вы решили что после прочтения <a href="http://hudson.su/?p=1032" target="_blank">первой части</a>, что стоит потратить на Symfony еще 10 минут? Отлично! Во второй части мы узнаем у системе шаблонов в Symfony. Как вы могли видеть ранее, Symfony использует PHP в качестве шаблонного движка по-умолчанию, добавляет несколько отличных возможностей, что делает его более мощным.</p>
<p><span id="more-1094"></span></p>
<ul>
<li><a href="http://hudson.su/?p=1032" target="_blank">Symfony 2.0 – быстрый тур – общая картинка (часть 1)</a></li>
<li><a href="http://hudson.su/?p=1174" target="_blank">Symfony 2.0 – быстрый тур – контроллер/the controller (часть 3)</a></li>
<li><a href="http://hudson.su/?p=1235" target="_blank">Symfony  2.0 – быстрый тур – пакеты/the bundles  (часть  4)</a></li>
<li><a href="http://hudson.su/?p=1321" target="_blank">Symfony 2.0 – быстрый тур – архитектура/the architecture (часть 5)</a></li>
</ul>
<h2>Декорирование шаблонов</h2>
<p>Очень часто, шаблоны в проектах используют общие элементы, например всем известные хидер (header) и футер (footer). В Symfony мы имеем по этому поводу свое мнение: <strong>шаблон может быть декорирован другим шаблоном</strong>. Давайте посмотрим на файл layout.php:</p>
<pre># src/Application/HelloBundle/Resources/views/layout.php
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;?php $view-&gt;slots-&gt;output('_content') ?&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Шаблон index декорируется шаблоном layout.php (спасибо extend()):</p>
<pre># src/Application/HelloBundle/Resources/views/Hello/index.php
&lt;?php $view-&gt;extend('HelloBundle::layout') ?&gt;

Hello &lt;?php echo $name ?&gt;!</pre>
<p>Нотация HelloBundle::layout звучит знакомо, не так ли? Это та же самая нотация для привязки шаблона. Часть &#8220;::&#8221; означает что контроллер пуст (не указан) и следовательно соответствующий файл хранится напрямую во views/.</p>
<p>Строка $view-&gt;slots-&gt;output(&#8216;_content&#8217;) заменяется контентом дочернего шаблона, index.php (про него подробнее в следующей секции).</p>
<p>Как вы можете видеть, Symfony предоставляет метод загадочного объекта $view. В шаблоне, $view это специальный объект, который предоставляет пачку методов и свойств, которые заставляют движок шаблонов &#8220;тикать как часы&#8221;.</p>
<p>Symfony также поддерживает множественные уровни декорации (multiple decoration levels): один layout может быть декорирован другим. Эта техника будет полезна для больших проектов и она становится еще более могущественной в комбинации со слотами (slots).</p>
<h2>Слоты.</h2>
<p>Что есть слот? Слот &#8211; это кусочек кода, определенный в шаблоне, который может быть использован в любом макете (layout), декорирующем шаблон. Определим слот title в шаблоне index:</p>
<pre># src/Application/HelloBundle/Resources/views/Hello/index.php
&lt;?php $view-&gt;extend('HelloBundle::layout') ?&gt;

&lt;?php $view-&gt;slots-&gt;set('title', 'Hello World app') ?&gt;

Hello &lt;?php echo $name ?&gt;!</pre>
<p>И изменим макет таким образом, чтобы title выводился в заголовке:</p>
<pre># src/Application/HelloBundle/Resources/views/layout.php
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;&lt;?php $view-&gt;slots-&gt;output('title', 'Default Title') ?&gt;&lt;/title&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;?php $view-&gt;slots-&gt;output('_content') ?&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Метод output() вставляет содержимое слота и опционально принимает значение по умолчанию, если слот не установлен. Также, _content является специализированным слотом, который содержит отрендереный шаблон дочернего шаблона.</p>
<p>Для больших слотов также есть расширенный синтаксис:</p>
<pre>&lt;?php $view-&gt;slots-&gt;start('title') ?&gt;
  Some large amount of HTML
&lt;?php $view-&gt;slots-&gt;stop() ?&gt;</pre>
<h2>Подключение других шаблонов.</h2>
<p>Наилучшим выходом, для того чтобы кусочек кода можно было использовать во многих различных шаблонах, будет определить определить шаблон, который может быть включен в любой другой шаблон.</p>
<p>Создадим шаблон hello.php:</p>
<pre># src/Application/HelloBundle/Resources/views/Hello/hello.php
Hello &lt;?php echo $name ?&gt;!</pre>
<p>И изменим шаблон index.php чтобы подключить его:</p>
<pre># src/Application/HelloBundle/Resources/views/Hello/index.php
&lt;?php $view-&gt;extend('HelloBundle::layout') ?&gt;

&lt;?php echo $view-&gt;render('HelloBundle:Hello:hello', array('name' =&gt; $name)) ?&gt;</pre>
<p>Метод render() вычисляет и возвращает содержимое другого шаблона (это точно такой же метод, который используется в контроллере).</p>
<h2>Встраивание других действий</h2>
<p>А что, если вы хотите отобразить результат другого действия в шаблоне? Это очень нужно при работе с Ajax или когда встраиваемый шаблон требует переменные, которые не определены в основном шаблоне.</p>
<p>Если вы создадите действие fancy и захотите включить его в шаблон шndex, просто используйте следующий код:</p>
<pre># src/Application/HelloBundle/Resources/views/Hello/index.php
&lt;?php $view-&gt;actions-&gt;output('HelloBundle:Hello:fancy', array('name' =&gt; $name, 'color' =&gt; 'green')) ?&gt;</pre>
<p>Здесь, строка HelloBundle::Hello::fancy ссылается на действие fancy контроллера Hello:</p>
<pre># src/Application/HelloBundle/Controller/HelloController.php
class HelloController extends Controller
{
  public function fancyAction($name, $color)
  {
    // create some object, based on the $color variable
    $object = ...;

    return $this-&gt;render('HelloBundle:Hello:fancy', array('name' =&gt; $name, 'object' =&gt; $object));
  }

  // ...
}</pre>
<p>Вы также должны иметь в виду, что эта техника очень мощная, но в то же время медленная, так как она порождает внутренний подзапрос (sub-request). Таким образом, везде где возможно &#8211; применяйте более быструю альтернативу.</p>
<p>Но где же определено свойство $view-&gt;actions? Как и $view-&gt;slots, оно вызывает хелпер шаблона и в следующей секции в узнаете об этом чуть больше!</p>
<h2>Хэлперы шаблонов</h2>
<p>Система шаблонов Symfony может быстро и просто быть расширена через хелперы. Хелперы это PHP объекты, которые предоставляют функционал, который требуется в шаблонах. actions и slots это лишь два, встроенных в Symfony, хелперов.</p>
<h3>Линки(связи) между страницами</h3>
<p>Говоря о веб-приложениях, вы должны всегда создавать ссылки между различными страницами. Вместо того чтобы хардкодить URL в шаблоне, хэлпер маршрутов (router helper) знает как создать URL, основываясь на конфигурации маршрутов. Таким образом, все URL могут быть легко и непринужденно изменены через конфигурацию.</p>
<pre>&lt;a href="&lt;?php echo $view-&gt;router-&gt;generate('hello', array('name' =&gt; 'Thomas')) ?&gt;"&gt;
  Greet Thomas!
&lt;/a&gt;</pre>
<p>Метод generate() принимает имя маршрута и массив аргументов. Имя маршрута это основной ключ, по которому маршрут можно найти и аргументы как минимум должны покрывать метки-плейсхолдеры в описании маршрута.</p>
<pre># src/Application/HelloBundle/Resources/config/routing.yml
hello: # The route name
  pattern:  /hello/:name
  defaults: { _bundle: HelloBundle, _controller: Hello, _action: index }</pre>
<h3>Использование ассетов (картинки, стили, скрипты)</h3>
<p>Каким бы был интернет без картинок, скриптов и стилей? Symfony предлагает три хелпера для упрощения работы с ними: assets, javaScripts и stylesheets.</p>
<pre>&lt;link href="&lt;?php echo $view-&gt;assets-&gt;getUrl('css/blog.css') ?&gt;" rel="stylesheet" type="text/css" /&gt;

&lt;img src="&lt;?php echo $view-&gt;assets-&gt;getUrl('images/logo.png') ?&gt;" /&gt;</pre>
<p>Назначение хелпера assets &#8211; сделать ваше приложение более переносимым (portable). Благодаря ему, вы можете переносить корень приложения куда вам угодно в рамках directory root без изменений в коде ваших шаблонов.</p>
<p>Таким же образом вы можете управлять стилями и яваскриптами при помощи хелперов stylesheets и javaScripts:</p>
<pre>&lt;?php $view-&gt;javascripts-&gt;add('js/product.js') ?&gt;
&lt;?php $view-&gt;stylesheets-&gt;add('css/product.css') ?&gt;</pre>
<p>Метод add() определяет зависимости. Для вывода ассетов вам нужно добавить следующий код в основной шаблон (layout):</p>
<pre>&lt;?php echo $view-&gt;javascripts ?&gt;
&lt;?php echo $view-&gt;stylesheets ?&gt;</pre>
<h2>Последний рывок</h2>
<p>Система шаблонов Symfony простая, но очень эффективная. Благодаря layot&#8217;ам, slot&#8217;ам, шаблонам и включению действий очень легко можно организовать ваши шаблоны логично и гибко. Позднее вы узнаете как конфигурировать поведение по умолчанию для шаблонизатора и как расширять ее, добавляя новые хелперы.</p>
<p>Итого, мы провели с Symfony что-то около 20 минут и вы уже можете делать много интересных вещей. Это сила Symfony. Изучить основы легко, но скоро  вы поймете, что эта простота скрывает очень гибкую архитектуру.</p>
<p>Но не будем забегать вперед. Для начала вам нужно изучить немного больше о контроллере и это будет темой нашего следующего занятия. Готовы выделить еще 10 минут для Symfony?</p>
<blockquote><p>Оригинал взят тут: <a href="http://symfony-reloaded.org/quick-tour-part-2" target="_blank">http://symfony-reloaded.org/quick-tour-part-2</a></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/03/12/symfony-2-0-quick-tour-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

