<?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; php</title>
	<atom:link href="http://hudson.su/tag/php/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>PhpStorm: поддержка Symfony Command Line</title>
		<link>http://hudson.su/2011/05/25/phpstorm-symfony-command-line-usage-with-command-line-tool-support/</link>
		<comments>http://hudson.su/2011/05/25/phpstorm-symfony-command-line-usage-with-command-line-tool-support/#comments</comments>
		<pubDate>Wed, 25 May 2011 08:57:10 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpstorm]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Symfony2]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1951</guid>
		<description><![CDATA[Начиная с PhpStorm 2.0 можно использовать Symfony command line tool при помощи Command Line Tool Support. Ниже приводится небольшое руководство по использованию. Вам понадобится PhpStorm 2.0 и Symfony 1.1 или более поздней версии (включая Symfony 2.0 BETA &#8211; в оригинальное руководство не входило, но мной проверено). Если у вас нет Symfony, руководство по установке вы [...]]]></description>
			<content:encoded><![CDATA[<p>Начиная с PhpStorm 2.0 можно использовать Symfony command line tool при помощи Command Line Tool Support.</p>
<p>Ниже приводится небольшое руководство по использованию. Вам понадобится <strong>PhpStorm 2.0</strong> и <strong>Symfony 1.1</strong> или более поздней версии (<strong>включая Symfony 2.0 BETA</strong> &#8211; в оригинальное руководство не входило, но мной проверено). Если у вас нет Symfony, руководство по установке вы можете найти <a href="http://www.symfony-project.org/getting-started/1_4/en/03-Symfony-Installation" target="_blank">здесь</a>.</p>
<p><span id="more-1951"></span></p>
<p>В первую очередь нам нужно настроить новый command line tool.</p>
<h3>Загрузка Symfony Commands</h3>
<p>Откройте меню <strong>Settings | Command Line Tool Support</strong> и нажмите в появившемся окне кнопку <strong>Add</strong>. Вам будет предложено три опции, выберите “<strong>Symfony</strong>”:</p>
<p><a rel="lightbox-01" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/Screenshot-Choose-Framework-To-Add.png"><img title="Choose Symfony framework to add" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/Screenshot-Choose-Framework-To-Add.png" alt="Choose Symfony Framework To Add" width="285" height="119" /></a></p>
<p>Затем укажите путь к файлу $Symfony_home$/data/bin/symfony. Для типичной конфигурации (из руководства симфони) путь будет следующим: $Project_root$/lib/vendor/symfony/data/bin/symfony. Описания команд Symfony будут загружены и сохранены в файл среди прочих настроек проекта. В диалоговом окне настроек это будет выглядеть следующим образом:</p>
<p><a rel="lightbox-02" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/symfonyDescriptionInSettings.png"><img title="Symfony description in Settings" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/symfonyDescriptionInSettings.png" alt="Symfony description in Settings" width="658" height="108" /></a></p>
<ul>
<li>Поле Tool Path содержит путь к CLI (php и фреймворка) и будет различаться в зависимости от фреймфорка. Для Symfony это &#8220;php  $path_to_symfony$&#8221;  и &#8220;$Zend_Framework_Tool_home$/bin/zf.bat&#8221; для Zend Framework. $PhpExecutable$ &#8211; это макрос, он заменяется на путь к исполнимому файлу CLI PHP, $ProjectFileDir$ это тоже макрос, он заменяется на полный путь к проекту. Макросы позволяют легко перемещать настройки между несколькими IDE.</li>
<li>Полный Tool Path может быть очень длинным и неудобным в наборе, поэтому имеется алиас, который представляет из себя строку, которую можно использовать для вызова CLI вместо Tool Path.</li>
<li>Чекбокс &#8220;Enable&#8221; поможет вам легко включать и отключать команды фреймворка из списка автоподстановки, не удаляя настройки. В данном случае чекбокс включен, таким образом команды Symfony будут отображаться в списке. Нажмите Ctrl +Shift+X или выберите в меню <strong>Tools | Run Command…</strong> и наберите алиас &#8220;s&#8221;:</li>
</ul>
<p><a rel="lightbox-03" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/commandList31.png"><img title="Symfony commands list" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/commandList31.png" alt="Symfony commands list" width="337" height="187" /></a></p>
<h3>Используем Symfony Command Line</h3>
<p>Теперь создадим простой проект на Symfony c использованием Command Line Tool, как это описано в “Getting  Started” <a href="http://www.symfony-project.org/getting-started/1_4/en/04-Project-Setup" target="_blank">документе</a>.</p>
<h4>Создаем проект Symfony</h4>
<p>Нажимаем Ctrl +Shift+X и набираем:</p>
<p><a rel="lightbox-04" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/symfonyGenerateProject.png"><img title="Generate project command" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/symfonyGenerateProject.png" alt="Generate project command" width="302" height="44" /></a></p>
<p>Команда имеет два параметра:</p>
<ul>
<li> Обязательный параметр “name”. Мы воспользуемся макросом $ProjectName$, который будет заменен на наименование проекта PhpStorm.</li>
<li>Опциональный параметр “author”.</li>
</ul>
<p>Перед выполнением команды макрос $ProjectName$ будет заменен на имя проекта и алиас “s” будет заменен на Tool Path. В данном случае это будет что-то типа “usr/bin/php  /home/sfproject/lib/vendor/symfony/data/bin/symfony”.</p>
<p>Результат &#8211; будет создан проект:</p>
<p><a rel="lightbox-05" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/generateProjectToolwindow2.png"><img title="Toolwindow with generated project" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/generateProjectToolwindow2.png" alt="Toolwindow with generated project" width="711" height="208" /></a></p>
<h4>Настройка доступа к базе данных</h4>
<p>Теперь настроим доступ к БД при помощи команды “php symfony  configure:database “mysql:host=localhost;dbname=dbname” root mYsEcret”</p>
<p><a rel="lightbox-06" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/confDatabasePopup2.png"><img title="Configuring database command" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/confDatabasePopup2.png" alt="Configuring database command" width="508" height="45" /></a></p>
<h4>Создание приложения Frontend</h4>
<p>Давайте создадим приложение frontend без экранирования вывода (что в общем-то сделает его менее защищенным!). Нажмите Ctrl +Shift+X и наберите:</p>
<p><a rel="lightbox-07" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/generateAppPopup2.png"><img title="Generate application command" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/generateAppPopup2.png" alt="Generate application command" width="346" height="44" /></a></p>
<p>Заметьте, что опции команд также поддерживаются. В примере выше это была опция –escaping-strategy=false.</p>
<p>Результат работы команды:</p>
<p><a rel="lightbox-08" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/dbAndAppToolWindows2.png"><img title="Commands output" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/dbAndAppToolWindows2.png" alt="Commands output" width="711" height="207" /></a></p>
<h4>Права доступа к директориям</h4>
<p>Следующим шагом является установка прав на директории cache/ и log/. Это также можно сделать при помощи Command Line Tool  Support. Тул попытается выполнить команды (макросы таже доступны). Но имейте в виду, что команды &#8220;chmod&#8221; по-умолчанию нет в windows системах (если вы не используете например cygwin).</p>
<p><a rel="lightbox-09" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/chmodPopup1.png"><img title="Chmod command" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/chmodPopup1.png" alt="Chmod command" width="347" height="45" /></a></p>
<p>Результат:</p>
<p><a rel="lightbox-10" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/chmodAndLsToolwindow21.png"><img title="Chmod and ls output in toolwindow" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/chmodAndLsToolwindow21.png" alt="Chmod and ls output in toolwindow" width="556" height="315" /></a></p>
<blockquote>
<h2>Примечание:</h2>
<p>Вообще говоря для установки прав <del>можно</del> нужно использовать команду &#8220;symfony project:permissions&#8221; // hudson@work</p></blockquote>
<p>После этого надо настроить web-сервер, как описано в <a href="http://www.symfony-project.org/getting-started/1_4/en/05-Web-Server-Configuration" target="_blank">документации</a>, и запустить его.</p>
<h3>Тестирование</h3>
<p>Проверьте доступ к новому приложению &#8211; откройте в браузере <a href="http://localhost:8080/index.php/" target="_blank">http://localhost:8080/index.php/</a> и затем проверьте доступ к dev окружению <a href="http://localhost:8080/frontend_dev.php/" target="_blank">http://localhost:8080/frontend_dev.php/</a>.</p>
<p>Если вы видите такую страницу, ваш проект успешно создан:</p>
<p><a rel="lightbox-11" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/finalPrintScreen.png"><img title="Project page" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/finalPrintScreen.png" alt="Project page" width="600" height="626" /></a></p>
<h3>Добавляем пользовательский task.</h3>
<p>Давайте создадим простой таск &#8220;hello&#8221;. Подразумевается что ранее вы уже настроили команды Symfony, как это описано выше и создали проект.</p>
<p>Нажмите Ctrl+Shift+X и выполните команду:</p>
<p><a rel="lightbox-12" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/generateTask2.png"><img title="Generate task command" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/generateTask2.png" alt="Generate task command" width="332" height="44" /></a></p>
<p>В директории lib/task будет создан класс “helloTask”.</p>
<p>Откройте класс helloTask в редакторе и выполните следующие несложные изменения в его методе “execute”:</p>
<p><a rel="lightbox-13" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/helloTaskContents2.png"><img title="HelloTask class execute function" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/helloTaskContents2.png" alt="HelloTask class execute function" width="463" height="153" /></a></p>
<p>Откройте description file для Symfony: выберите <strong>Settings |  Command Line Tool Support</strong> и нажмите кнопку “Open definition in editor”.</p>
<p>Добавьте описание новой команды “hello”:</p>
<p><a rel="lightbox-14" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/newCommandDescription.png"><img title="Hello command description" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/newCommandDescription.png" alt="Hello command description" width="464" height="261" /></a></p>
<p>Текст описания:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;command<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        hello
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;help<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        My first task with no parameters.
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/help<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/command<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Для проверки новой команды выполните:</p>
<p><a rel="lightbox-15" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/helloList.png"><img title="Hello command" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/helloList.png" alt="Hello command" width="336" height="54" /></a></p>
<p>Результат выполнения отобразится в консоли:</p>
<p><a rel="lightbox-16" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/helloInvoker2.png"><img title="Hello, invoker!" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/helloInvoker2.png" alt="Hello, invoker!" width="607" height="118" /></a></p>
<h4>Решение проблем</h4>
<p>Если у вас возникнут проблемы после редактирования файла описания и нужная вам команда не появится, откройте таб Validation в консоли. Этот таб показывает информацию о проблемах парсинга файла описания:</p>
<p><a rel="lightbox-17" href="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/validationTab.png"><img title="Validation tab" src="http://blogs.jetbrains.com/webide/wp-content/uploads/2011/01/validationTab.png" alt="Validation tab" width="487" height="85" /></a></p>
<p>Вы также можете получить информацию о формате файла описания из схемы .idea/commandlinetools/schemas/frameworkDescriptionVersion1.1.xsd. Этот путь указан в созданном файле описания и редактор выполняет валидацию автоматически с его использованием.</p>
<blockquote><p>Hope this hepls как говорится, ваш hudson@work <img src='http://hudson.su/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2011/05/25/phpstorm-symfony-command-line-usage-with-command-line-tool-support/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Symfony2: аналог preExecute() для контроллера</title>
		<link>http://hudson.su/2011/04/20/symfony2-preexecute-analog/</link>
		<comments>http://hudson.su/2011/04/20/symfony2-preexecute-analog/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 16:42:28 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[Symfony2]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1910</guid>
		<description><![CDATA[Я думаю многих смущает отсутствие preExecute в стандартном контроллере Symfony2. Ниже я приведу возможное решение данного вопроса при помощи внедрения зависимости через Service Container (Оригинал подсмотрен у Szymon Szewczyk). UPDATE 20 января 2012: статья обновлена в соответствии с современными реалиями SF 2.0.9 (фактически изменения коснулись именования тага и события) Итак, начнем с определения службы: YAML: [...]]]></description>
			<content:encoded><![CDATA[<p>Я думаю многих смущает отсутствие preExecute в стандартном контроллере Symfony2. Ниже я приведу возможное решение данного вопроса при помощи внедрения зависимости через Service Container (Оригинал подсмотрен у Szymon Szewczyk).</p>
<blockquote><p><strong>UPDATE 20 января 2012:</strong> статья обновлена в соответствии с современными реалиями SF 2.0.9 (фактически изменения коснулись именования тага и события)</p></blockquote>
<p><span id="more-1910"></span>Итак, начнем с определения службы:</p>
<p><strong>YAML:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;"># Vendor\MyBundle\Resources\config.yml
services:
    # ...
    preexecute.listener:
        class: Vendor\MyBundle\Listener\PreExecuteListener
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }</pre></div></div>

<p><strong>XML:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"># Vendor\MyBundle\Resources\config.xml
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;kernel.listener.pre_execute&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Vendor\MyBundle\Listener\PreExecuteListener&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tag</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;kernel.event_listener&quot;</span> <span style="color: #000066;">event</span>=<span style="color: #ff0000;">&quot;kernel.controller&quot;</span> <span style="color: #000066;">method</span>=<span style="color: #ff0000;">&quot;onKernelController&quot;</span> <span style="color: #000066;">priority</span>=<span style="color: #ff0000;">&quot;0&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Создадим также определение нашей службы в положенном ей месте:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Vendor\MyBundle\Listener\PreExecuteListener.php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">namespace</span> Vendor\MyBundle\Listener<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\EventDispatcher\Event<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\HttpKernel\HttpKernelInterface<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\HttpKernel\Event\FilterControllerEvent<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> PreExecuteListener
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> onKernelController<span style="color: #009900;">&#40;</span>FilterControllerEvent <span style="color: #000088;">$event</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>HttpKernelInterface<span style="color: #339933;">::</span><span style="color: #004000;">MASTER_REQUEST</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$event</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getRequestType<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$controllers</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$event</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getController<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #666666; font-style: italic;">// контроллер должен существовать</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$controllers</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$controllers</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// метод должен существовать</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">method_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$controller</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'preExecute'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
          <span style="color: #000088;">$controller</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>preExecute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Вот и все! ) Теперь в нужном контроллере объявляем метод <code>preExecute()</code> и наслаждаемся нашими танцами с бубном )</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2011/04/20/symfony2-preexecute-analog/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Symfony2 Глоссарий</title>
		<link>http://hudson.su/2011/03/28/symfony2-glossary/</link>
		<comments>http://hudson.su/2011/03/28/symfony2-glossary/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 14:29:49 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[web разработка]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1863</guid>
		<description><![CDATA[Для того чтобы эффективно общаться между собой, люди (и программисты не исключение) заранее договариваются о некоторой базовой терминологии, поэтому перевод Symfony2 the Book, я хочу начать с небольшого глоссария, терминологию которого я буду использовать в дальнейшем. Приложение (Application) Под Приложением мы будем понимать директорию, содержащую конфигурацию для данного конкретного набора пакетов. Пакет (Bundle) Пакет, это [...]]]></description>
			<content:encoded><![CDATA[<p>Для того чтобы эффективно общаться между собой, люди (и программисты не исключение) заранее договариваются о некоторой базовой терминологии, поэтому перевод <strong>Symfony2 the Book</strong>, я хочу начать с небольшого глоссария, терминологию которого я буду использовать в дальнейшем.</p>
<p><span id="more-1863"></span></p>
<dl>
<h3 id="term-application">Приложение (Application)</h3>
<dd> Под Приложением мы будем понимать директорию, содержащую <em>конфигурацию </em>для данного конкретного набора пакетов. </dd>
<h3 id="term-bundle">Пакет (Bundle)</h3>
<dd> Пакет, это директория, содержащая набор файлов (PHP, CSS, JavaScript, изображения), которые реализуют одну более-менее крупную функцию (блог, форум и т.д.). В Symfony2 всё (в основном) располагается внутри тех или иных пакетов. (<a href="http://symfony.com/doc/2.0/glossary/book/page_creation.html#page-creation-bundles" target="_blank"><em>The Bundle System</em></a>) </dd>
<h3 id="term-distribution">Дистрибутив (Distribution)</h3>
<dd>Дистрибутив &#8211; это совокупность компонент Symfony2, выбранных пакетов, соответствующей структуры директорий, конфигурации по-умолчанию и опциональной системы конфигурирования. (<em>Примечание: название &#8220;дистрибутив&#8221; показалось мне наиболее логичным в данном случае, слово конечно заимствованное, но в среде ИТ-шников все его знают, в то же время &#8220;дистрибьюция&#8221; &#8211; это уже что-то из мира продаж имхо</em>).</dd>
<h3 id="term-front-controller">Фронт-контроллер (Front Controller)</h3>
<dd>Фронт-контроллер, это короткий PHP-файл, который расположен в web-директории проекта. Обычно все запросы перехватываются фронт-контроллером, а основная его задача состоит в загрузке Symfony-приложения.</dd>
<h3 id="term-http-specification">Спецификация протокола HTTP (HTTP Specification)</h3>
<dd> Спецификация протокола HTTP &#8211; это документ, который описывает протокол передачи гипертекста &#8211; набор правил, описывающих классическую клиент-серверную коммуникацию, базирующуюся на запросах и ответах. Спецификация определяет формат, используемый для запросов и ответов, а также всевозможные HTTP заголовки, которые каждый запрос/ответ могут иметь. За дополнительной информацией о протоколе HTTP вы можете обратиться по ссылкам: <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">Http Wikipedia</a> и <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">HTTP 1.1 RFC</a>.</dd>
<h3>Окружение (Environment)</h3>
<dd>Окружение это наименование (например prod или dev) совокупности параметров, которое соответствет некоторому набору конфигурационных параметров. Одно и то же приложение может быть запущено с использованием различных конфигураций посредством его запуска в различных окружениях. Это очень удобно, так как позволяет для одного приложения иметь <strong>dev</strong>[elopment] окружение для отладки и <strong>prod</strong>[uction] окружение, оптимизированное по скорости &#8211; для конечного пользователя.</dd>
<h3>Проект (Project)</h3>
<dd>Проект &#8211; это директория, состоящая из приложения, набора пакетов, сторонних библиотек, автозагрузчика и скрипта фронт-контроллера.</dd>
<h3 id="term-service">Служба (Service)</h3>
<dd>Служба &#8211; это базовый термин для любого объекта в PHP, который выполняет определнную задачу. Служба как правило используется глобально, например объект подключения к базе данных или объект для отправки email сообщений. О приложении, имеющим много независимых служб, говорят что оно реализует <a href="http://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%B0%D1%8F_%D0%B0%D1%80%D1%85%D0%B8%D1%82%D0%B5%D0%BA%D1%82%D1%83%D1%80%D0%B0" target="_blank">сервисно-ориентированную архитектуру</a>.</dd>
<h3 id="term-service-container">Контейнер служб (Service Container)</h3>
<dd>Контейнер служб, также известный как Контейнер внедрения зависимости (<em>Dependency Injection Container</em>), это специальный объект, который управляет созданием экземпляров сервисов внутри приложения. Вместо того, чтобы создавать сервис напрямую, разработчик посредством конфигурации обучает контейнер служб как создавать тот или иной сервис. Контейнер служб в свою очередь позаботится о простом получении экземпляра службы и внедрения зависимых служб.</dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2011/03/28/symfony2-glossary/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>( PHP CLI &amp; eAccelerator ) != love</title>
		<link>http://hudson.su/2011/02/16/php-cli-and-eaccelerator-ne-love/</link>
		<comments>http://hudson.su/2011/02/16/php-cli-and-eaccelerator-ne-love/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 10:49:18 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[eaccelerator]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[web разработка]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1774</guid>
		<description><![CDATA[На днях встал вопрос об оптимизации запуска cron-скриптов. Подавляющая часть &#8211; это таски symfony (т.е. выполняется что-то типа ./symfony namespace:taskname params) и даже в условиях использования nice они создают приличный оверхед на сервер. В ходе разбора полетов решил уяснить, работает ли eAccelerator c php-cli. Собственно с подсказки @ibulatenko забрел на страницу http://eaccelerator.net/wiki/Faq, на которой черным [...]]]></description>
			<content:encoded><![CDATA[<p>На днях встал вопрос об оптимизации запуска cron-скриптов. Подавляющая часть &#8211; это таски symfony (т.е. выполняется что-то типа ./symfony namespace:taskname params) и даже в условиях использования nice они создают приличный оверхед на сервер.</p>
<p>В ходе разбора полетов решил уяснить, работает ли eAccelerator c php-cli. Собственно с подсказки <a href="http://twitter.com/ibulatenko" target="_blank">@ibulatenko</a> забрел на страницу <a href="http://eaccelerator.net/wiki/Faq" target="_blank">http://eaccelerator.net/wiki/Faq</a>, на которой черным по вебу написано в самом низу страницы:</p>
<blockquote><p><strong>Is eAccelerator working with php-cgi or php-cli?</strong><br />
This is not yet supported and it won&#8217;t be supported in the near future. However FastCGI <strong>is</strong> supported.</p></blockquote>
<p>P.S. Судя по всему ни один акселератор не работает при использовании CLI интерфейса (по крайней мере точно известно про XCache, при этом там также написано что поскольку у CLI совершенно другой принцип работы, то и ожидать не стоит).</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2011/02/16/php-cli-and-eaccelerator-ne-love/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Валидация email в стиле Swift Mailer</title>
		<link>http://hudson.su/2010/11/02/email-validation-swift-mailer-style/</link>
		<comments>http://hudson.su/2010/11/02/email-validation-swift-mailer-style/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 08:24:19 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[swift mailer]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1656</guid>
		<description><![CDATA[Довелось на днях играться с email-рассылкой в symfony 1.4 при помощи Swift mailer. Тема массовых рассылок достойна отдельного поста, поэтому пока остановлюсь на валидации email в стиле Swift. Зачем вообще понадобилась такая валидация? Как раз об этом я и собирался рассказать: Имеем цикл по получателям, который чанками (страницами, как вам будет удобнее) обходит всех наших [...]]]></description>
			<content:encoded><![CDATA[<p>Довелось на днях играться с email-рассылкой в symfony 1.4 при помощи Swift mailer. Тема массовых рассылок достойна отдельного поста, поэтому пока остановлюсь на валидации email в стиле Swift. Зачем вообще понадобилась такая валидация? Как раз об этом я и собирался рассказать:</p>
<p><span id="more-1656"></span></p>
<p>Имеем цикл по получателям, который чанками (страницами, как вам будет удобнее) обходит всех наших потенциальных получателей. Каждый чанк формирует свою партию писем посредством <code>Swift_Mailer::batchSend()</code>. И вот допустим ситуацию, когда <span style="text-decoration: line-through">враги сожгли родную хату</span>&#8230; нет не так, враги заменили несколько email на нечто, не соответствующее требованиям RFC. Что произойдет? А то и произойдет &#8211; Swift вызовет исключение и</p>
<p>а) процесс рассылки вообще упадет, если <code>try ... catch</code> у вас нет</p>
<p>б) чанк выпадет из рассылки, если <code>try ... catch</code> у вас есть.</p>
<p>Обе ситуации мне лично не нравятся. Поэтому я решил произвести валидацию адреса до фактического попадания его в чанк.</p>
<p>Первая инкарнация использовала <code>sfValidatorEmail</code> (ну конечно, он предназначен для использования в формах, но если немного попрыгать с бубном и добавить к этому<code> try ... catch</code> &#8211; получается более менее юзабельно (<code>clean()</code> в <code>sfValidatorRegex</code> тоже кастует исключение, ага). Тем не менее тестирование выявило несостоятельность такого подхода, так как <code>sfValidatorEmail</code> в некоторых случаях не отлавливал несоответствия RFC.</p>
<p>Логично в этом месте воспользоваться встроенным в Swift механизмом валидации. Ан не тут то было. Публично доступного валидатора я не нашел, греп по коду выявил что валидация происходит в недрах класса <code>Swift_Mime_Headers_AbstractHeader</code> (да, абстрактного класса), ну или если ближе к народу, то в <code>Swift_Mime_Headers_MailboxHeader</code> (кстати загляните в реализацию &#8211; на мой вкус и цвет это самый большой регэксп на email который я когда либо видел!).</p>
<p>Итого, вот сниппет валидации:</p>
<pre>&lt;?php
...
// энкодер - нужен для инициализации MailboxHeader
$encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder();
...
// цикл по получателям в текущем чанке
foreach( ... )
{
  try
  {
    // собственно валидация. обязательно используйте try/catch
    $header = new Swift_Mime_Headers_MailboxHeader( 'To', $encoder );
    $header-&gt;setNameAddresses( array( $email ) );
    // если тут не упали с исключением, адрес валидный - добавляем в нашу пачку получателей
    ...
  }
  catch( Exception $e )
  {
    // email невалидный - следующая итерация
    continue;
  }
}
...
</pre>
<p>Дочитали до этого места? Прониклись значимостью идеи? А теперь забудьте его&#8230; страшненько оно как-то смотрится!</p>
<p>p.s. если знаете более цивилизованный способ валидации по версии Swift &#8211; напишите пожалуйста )</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/11/02/email-validation-swift-mailer-style/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Symfony 2 &amp; Facebook: часть 1, первый проект</title>
		<link>http://hudson.su/2010/09/06/symfony-2-facebook-part-1-first-project/</link>
		<comments>http://hudson.su/2010/09/06/symfony-2-facebook-part-1-first-project/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 15:27:02 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[facebook graph api]]></category>
		<category><![CDATA[facebook php sdk]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Symfony2]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1568</guid>
		<description><![CDATA[Уже совсем скоро (хочется надеяться) будет выпущен первый релиз Symfony 2. А по сему пробуем применить его на практике. Этим постом я планирую начать небольшую серию публикаций про работу с Symfony 2 и Facebook на php 5.3. Что из этого выйдет &#8211; время покажет, а пока делаем первые шаги: Для начала качаем sandbox Symfony 2: [...]]]></description>
			<content:encoded><![CDATA[<p>Уже совсем скоро (хочется надеяться) будет выпущен первый релиз <strong>Symfony 2</strong>. А по сему пробуем применить его на практике.</p>
<p>Этим постом я планирую начать небольшую серию публикаций про работу с <strong>Symfony 2</strong> и <strong>Facebook</strong> на php 5.3. Что из этого выйдет &#8211; время покажет, а пока делаем первые шаги:</p>
<p><span id="more-1568"></span>Для начала качаем sandbox Symfony 2: <a href="http://symfony-reloaded.org/downloads/sandbox_2_0_PR2.zip" target="_blank">http://symfony-reloaded.org/downloads/sandbox_2_0_PR2.zip</a></p>
<p>Я экспериментирую на локальной машине с <strong>denwer</strong>&#8216;ом. У вас може быть <strong>XAMPP</strong>, <strong>MAMP </strong>или любая другая работоспособная комбинация из вебсервера и PHP 5.3.2+ (у меня установлен <strong>PHP 5.3.3</strong>).</p>
<p>Создаем директорию z:hometest-project.com и распаковываем содержимое сандбокса в нее. Получится примерно следующее:</p>
<pre>z:hometest-project.com
    hello
    src
    web</pre>
<p>Web не мудрствуя лукаво переименуем в www чтобы не возиться с ручным конфигом и hosts (в этом случае денвер сделает все настройки самостоятельно. Иначе &#8211; вам придется сделать их самим, что займет лишние 2 минуты). Не забываем рестартануть денвера.</p>
<p>Далее качаем с <strong>github </strong>тем или иным способом <strong>facebook php sdk</strong>: <a href="http://github.com/facebook/php-sdk/" target="_blank">http://github.com/facebook/php-sdk/</a>. Нас оттуда интересует файл src/facebook.php. Сразу предупрежу &#8211; я поступил немного грязно и разделил этот класс на два (их там и есть два, собственно <strong>Facebook </strong>и <strong>FacebookApiExcetion</strong>), а также разместил в namespace Facebook. Выглядит это примерно так:</p>
<pre>// src/vendor/facebook/Facebook/Facebook.php
&lt;?php

namespace Facebook;

if (!function_exists('curl_init')) {
  throw new Exception('Facebook needs the CURL PHP extension.');
}
if (!function_exists('json_decode')) {
  throw new Exception('Facebook needs the JSON PHP extension.');
}

/**
 * Provides access to the Facebook Platform.
 *
 * @author Naitik Shah &lt;naitik@facebook.com&gt;
 */
class Facebook
{
</pre>
<p>И вот так:</p>
<pre>// src/vendor/facebook/Facebook/FacebookApiException.php
&lt;?php

namespace Facebook;

/**
 * FacebookApiException
 *
 * @author     dmitry.bykadorov@gmail.com
 * @version    SVN: $Id:  $
 */

/**
 * Thrown when an API call returns an exception.
 *
 * @author Naitik Shah &lt;naitik@facebook.com&gt;
 */
class FacebookApiException extends Exception
{
</pre>
<p>Обратите внимание на строку <code>class FacebookApiException extends <strong>Exception</strong></code>. Мы используем стандартный класс Exception, который не принадлежит никакому пространству имен. Ну или принадлежит корневому (стандартному) пространству имен. Честно говоря я пока не очень продвинут в работе с неймспейсами, поэтому в терминологии могу ошибаться ).</p>
<p>Как вы можете видеть, файлы классов расположены в директории src/vendor/facebook/Facebook/. Разработчики Symfony 2 рекомендуют не включать сторонние библиотеки в бандлы или приложения &#8211; думаю стоит к этому прислушаться. Поэтому после размещения библиотеки в нашем приложении нам нужно зарегистрировать его в автолоадере. Для того открываем файл src/autoload.php и добавляем туда наш неймспейс в функцию registerNamespaces:</p>
<pre>// src/autoload.php
//...

$loader = new UniversalClassLoader();

$loader-&gt;registerNamespaces(array(
  'Symfony'                    =&gt; __DIR__.'/vendor/symfony/src',
  'Application'                =&gt; __DIR__,
  'Bundle'                     =&gt; __DIR__,
  'Doctrine\Common'           =&gt; __DIR__.'/vendor/doctrine/lib/vendor/doctrine-common/lib',
  'Doctrine\DBAL\Migrations' =&gt; __DIR__.'/vendor/doctrine-migrations/lib',
  'Doctrine\ODM\MongoDB'     =&gt; __DIR__.'/vendor/doctrine-mongodb/lib',
  'Doctrine\DBAL'             =&gt; __DIR__.'/vendor/doctrine/lib/vendor/doctrine-dbal/lib',
  'Doctrine'                   =&gt; __DIR__.'/vendor/doctrine/lib',
  'Zend'                       =&gt; __DIR__.'/vendor/zend/library',
  'Facebook'                   =&gt; __DIR__.'/vendor/facebook/lib',
));
//...
</pre>
<p>Для реализации тестового примера нам потребуется одна страница, поэтому структуру сандбокса с application bundle <strong>hello</strong> мы менять не будем (кроме того я пока не придумал зачем нам нужен будет бандл Facebook, поэтому это будет тема следующей статьи).</p>
<p>Создаем iframe приложение Facebook в разделе разработчиков (на этом отдельно не останавливаюсь, статью напишу <strong>если попросите</strong>). Оттуда нам нужны параметры приложения &#8211; app_id, api_key, app_secret. Второй параметр для <strong>oAuth </strong>не используется, но может будет полезен впоследствии. Наши настройки мы внесем в файл настроек hello/config/config.yml:</p>
<pre># hello/config/config.yml
parameters:
    kernel.include_core_classes: false

    # facebook
    facebook.credentials.app_id: &lt;ваш_app_id&gt;
    facebook.credentials.api_key: &lt;ваш_api_key&gt;
    facebook.credentials.app_secret: &lt;ваш_app_secret&gt;
    facebook.url.canvas:  # будет нужен потом
    facebook.url.site:  # будет нужен потом
</pre>
<p>Модифицируем HelloController:</p>
<pre>// src/Application/HelloBundle/Controller/HelloController.php
&lt;?php

  namespace ApplicationHelloBundleController;

  use Facebook;
  use SymfonyFrameworkFoundationBundleController;

  class HelloController extends Controller
  {
    public function indexAction($name)
    {
      $app_id = $this-&gt;container-&gt;getParameter('facebook.credentials.app_id');
      $api_key = $this-&gt;container-&gt;getParameter('facebook.credentials.api_key');
      $app_secret = $this-&gt;container-&gt;getParameter('facebook.credentials.app_secret');

      // у меня локально без отключения проверки сертификатов не заработало
      FacebookFacebook::$CURL_OPTS[CURLOPT_SSL_VERIFYHOST] = 0;
      FacebookFacebook::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = 0;

      $facebook = new FacebookFacebook(
      array(
        'appId' =&gt; $app_id,
        'secret' =&gt; $app_secret,
        'cookie' =&gt; true,
      ));
      $session = $facebook-&gt;getSession();

      $me = null;
      $uid = null;

      // Обращение к API на основе сессии
      if ($session)
      {
        try
        {
          $uid = $facebook-&gt;getUser();
          $me = $facebook-&gt;api('/me');
        }
        catch ( FacebookFacebookApiException $e )
        {
          // пока ничего не делаем
        }
      }

      // login или logout url будут нужны в зависимости от статуса авторизации пользователя
      $logoutUrl = '';
      $loginUrl = '';
      if ($me)
      {
        $logoutUrl = $facebook-&gt;getLogoutUrl();
      }
      else
      {
        $loginUrl = $facebook-&gt;getLoginUrl();
      }

      // Обращение к API без сессии
      $user = $facebook-&gt;api('/dmitry.bykadorov');

      return $this-&gt;render(
        'HelloBundle:Hello:index',
        array(
          'facebook' =&gt; $facebook,
          'session' =&gt; $session,
          'me' =&gt; $me,
          'logoutUrl' =&gt; $logoutUrl,
          'loginUrl' =&gt; $loginUrl,
          'user' =&gt; $user,
          'uid' =&gt; $uid,
        )
      );
    }
  }
</pre>
<p>Теперь нужно модифицировать шаблон: добавить в него декоратор (layout &#8211; он теперь не цепляется по умолчанию) и сформируем шаблон:</p>
<pre>&lt;?php
&lt;!-- src/Application/HelloBundle/Resources/views/Hello/index.php --&gt;
/**
 *
 */

?&gt;

&lt;?php $view-&gt;extend('HelloBundle::layout') ?&gt;

&lt;div id="fb-root"&gt;&lt;/div&gt;

&lt;style&gt;
 body {
 font-family: 'Lucida Grande', Verdana, Arial, sans-serif;
 }
 h1 a {
 text-decoration: none;
 color: #3b5998;
 }
 h1 a:hover {
 text-decoration: underline;
 }
&lt;/style&gt;

&lt;script&gt;
 window.fbAsyncInit = function()
 {
 FB.init({
 appId   : '&lt;?php echo $facebook-&gt;getAppId(); ?&gt;',
 session : &lt;?php echo json_encode($session); ?&gt;, // не фетчим сессию если она уже есть в PHP
 status  : true, // разрешаем проверку логина
 cookie  : true, // разрешаем куки для проверки сессии
 xfbml   : true // разрешаем парсинг XFBML
 });

 // если юзер вошел надо обновить страницу
 FB.Event.subscribe('auth.login', function()
 {
 window.location.reload();
 });
 };

 (function() {
 var e = document.createElement('script');
 e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
 e.async = true;
 document.getElementById('fb-root').appendChild(e);
 }());
&lt;/script&gt;

&lt;h1&gt;&lt;a href="example.php"&gt;php-sdk&lt;/a&gt;&lt;/h1&gt;

&lt;?php if ($me): ?&gt;
&lt;a href="&lt;?php echo $logoutUrl; ?&gt;"&gt;
 &lt;img src="http://static.ak.fbcdn.net/rsrc.php/z2Y31/hash/cxrz4k7j.gif"&gt;
&lt;/a&gt;
&lt;?php else: ?&gt;
&lt;div&gt;
 С использованием JavaScript &amp;amp; XFBML:
 &lt;fb:login-button&gt;&lt;/fb:login-button&gt;
&lt;/div&gt;
&lt;div&gt;
 Без JavaScript &amp;amp; XFBML:
 &lt;a href="&lt;?php echo $loginUrl; ?&gt;"&gt;
 &lt;img src="http://static.ak.fbcdn.net/rsrc.php/zB6N8/hash/4li2k73z.gif"&gt;
 &lt;/a&gt;
&lt;/div&gt;
&lt;?php endif ?&gt;

&lt;h3&gt;Сессия&lt;/h3&gt;
&lt;?php if ($me): ?&gt;
&lt;pre&gt;&lt;?php print_r($session); ?&gt;&lt;/pre&gt;

&lt;h3&gt;Вы&lt;/h3&gt;
&lt;img src="https://graph.facebook.com/&lt;?php echo $uid; ?&gt;/picture"&gt;
&lt;?php echo $me['name']; ?&gt;

&lt;h3&gt;Ваш юзерский объект&lt;/h3&gt;
&lt;pre&gt;&lt;?php print_r($me); ?&gt;&lt;/pre&gt;
&lt;?php else: ?&gt;
&lt;strong&gt;&lt;em&gt;Вы не подключены.&lt;/em&gt;&lt;/strong&gt;
&lt;?php endif ?&gt;

&lt;h3&gt;Юзер&lt;/h3&gt;
&lt;img src="https://graph.facebook.com/dmitry.bykadorov/picture"&gt;
&lt;?php echo $user['name']; ?&gt;</pre>
<p>Ну и немного подправим декорирующий шаблон:</p>
<pre>&lt;!-- src/Application/HelloBundle/Resources/views/layout.php --&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns:fb="http://www.facebook.com/2008/fbml"&gt;
&lt;head&gt;
 &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&gt;
&lt;/head&gt;
&lt;body&gt;

 &lt;table style="width:700px;margin-left:auto;margin-right:auto;" border="1"&gt;
 &lt;tr&gt;
 &lt;td&gt;
 &lt;?php $view-&gt;slots-&gt;output('_content') ?&gt;
 &lt;/td&gt;
 &lt;/tr&gt;
 &lt;/table&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>В результате мы поимеем примерно следующее:</p>
<p><a href="http://hudson.su/files/2010/09/symfony2_facebook_c1_01.png" rel='lightbox'><img class="alignnone size-medium wp-image-1596" src="http://hudson.su/files/2010/09/symfony2_facebook_c1_01-266x300.png" alt="" width="266" height="300" /></a></p>
<p>So&#8230; рубикон перейден, надеюсь мы с вами тут же на бережку не разляжемся а двинемся дальше )) </p>
<p>Have fun! ))</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/09/06/symfony-2-facebook-part-1-first-project/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Doctrine forms &#8211; редактирование i18n контента</title>
		<link>http://hudson.su/2010/06/04/doctrine-forms-editing-i18n-content/</link>
		<comments>http://hudson.su/2010/06/04/doctrine-forms-editing-i18n-content/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 07:44:23 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1549</guid>
		<description><![CDATA[Данная заметка не открывает ничего нового, тем не менее, подобные вопросы постоянно возникают, в том числе и у меня. Суть проблемы: есть i18n таблица (вернее пара таблиц, например content и content_translation). Хочется быстро и просто сделать в админке редактирование данных для нескольких языков. Оказывается, Doctrine form &#8220;из коробки&#8221; это умеет. Необходимо лишь выполнить несложное конфигурирование: [...]]]></description>
			<content:encoded><![CDATA[<p>Данная заметка не открывает ничего нового, тем не менее, подобные вопросы постоянно возникают, в том числе и у меня.</p>
<p><span id="more-1549"></span>Суть проблемы: есть i18n таблица (вернее пара таблиц, например content и content_translation). Хочется быстро и просто сделать в админке редактирование данных для нескольких языков.</p>
<p>Оказывается, Doctrine form &#8220;из коробки&#8221; это умеет. Необходимо лишь выполнить несложное конфигурирование:</p>
<pre>&lt;?php
class ContentForm extends BaseContentForm
{
  public function configure()
  {
    // ...
    $this-&gt;embedI18n(array('en', 'ru'));
    $this-&gt;widgetSchema-&gt;setLabel('en', 'Английская версия');
    $this-&gt;widgetSchema-&gt;setLabel('ru', 'Русская версия');
    // ...
  }
}
?&gt;
</pre>
<p>Этот прием описан в Jobeet, день 19: <a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/19#chapter_19_sub_admin_generator" target="_blank">http://www.symfony-project.org/jobeet/1_4/Doctrine/en/19#chapter_19_sub_admin_generator</a>, но, похоже, мало кто дочитывает до этого места.</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/06/04/doctrine-forms-editing-i18n-content/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Сниппет: загружаем переменные app.yml из CLI task в symfony</title>
		<link>http://hudson.su/2010/06/03/snippet-loads-app-yml-in-cli-task-in-symfony/</link>
		<comments>http://hudson.su/2010/06/03/snippet-loads-app-yml-in-cli-task-in-symfony/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 06:58:32 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1541</guid>
		<description><![CDATA[В ходе обсуждения в русскоязычном чате пользователей symfony возник вопрос о загрузке конфигурационных констант из app.yml в контексте CLI таска. Как правило, с теми классами, которые работают из-под приложения (frontend, backend или что там у вас), проблем не возникает. Не зависимо от того на каком уровне расположен app.yml, к нему можно получить доступ стандартными средствами [...]]]></description>
			<content:encoded><![CDATA[<p>В ходе обсуждения в русскоязычном чате пользователей symfony возник вопрос о загрузке конфигурационных констант из app.yml в контексте CLI таска. Как правило, с теми классами, которые работают из-под приложения (frontend, backend или что там у вас), проблем не возникает. Не зависимо от того на каком уровне расположен app.yml, к нему можно получить доступ стандартными средствами через <code>sfConfig::get()</code>.</p>
<p>В тасках же конфигурация уровня приложения не инициализируется, поэтому <code>sfConfig::get('app_some_param')</code> будет возвращать NULL. Немного покопавшись в API родился такой сниппет-скелетон таска:<span id="more-1541"></span></p>
<pre>&lt;?php
/**
 * @package
 * @subpackage task
 * @author     dmitry.bykadorov@gmail.com
 * @version    SVN: $Id:  $
 */
class TestTask extends sfBaseTask
{
  protected function configure()
  {
    $this-&gt;namespace = 'sf';
    $this-&gt;name = 'test';
    $this-&gt;briefDescription = 'TODO';

    $this-&gt;detailedDescription = &lt;&lt;&lt;EOF
TODO
EOF;
  }

  protected function execute($arguments = array(), $options = array())
  {
    $configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', true);
    var_dump( sfConfig::get( "app_some_param" ) );
  }
}
</pre>
<p>Протестировано на <code>sf_root_dir/config/app.yml</code></p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/06/03/snippet-loads-app-yml-in-cli-task-in-symfony/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>DevConf 2010</title>
		<link>http://hudson.su/2010/05/18/devconf-2010/</link>
		<comments>http://hudson.su/2010/05/18/devconf-2010/#comments</comments>
		<pubDate>Tue, 18 May 2010 16:49:49 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[devconf]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web разработка]]></category>
		<category><![CDATA[события]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1498</guid>
		<description><![CDATA[17го мая в Москве состоялась очередная конференция PHPConf, которая на этот раз сделала еще один level up и разрослась до масштабного мероприятия под названием DevConf. Да разрослась так, что пригласила всех своих друзей в гости: Perl, Ruby, Python, .Net. И я там был, мед-пиво пил (хотя вру, пиво не пил ))). Вкратце расскажу что же [...]]]></description>
			<content:encoded><![CDATA[<p>17го мая в Москве состоялась очередная конференция PHPConf, которая на этот раз сделала еще один level up и разрослась до масштабного мероприятия под названием DevConf. Да разрослась так, что пригласила всех своих друзей в гости: Perl, Ruby, Python, .Net. И я там был, мед-пиво пил (хотя вру, пиво не пил ))). Вкратце расскажу что же там было интересного и познавательного.</p>
<p><span id="more-1498"></span>Честно говоря организаторы немного недооценили масштаб бедствия, поэтому регистрация участников задержалась минут на 40, в результате чего главный зал отставал от программы на это время (до обеда примерно) и из-за чего был упразднен круглый стол по веб технологиям в пользу выступления приглашенных зарубежных гостей. Ну не очень то и хотелось )</p>
<p>Первым докладом я послушал <a href="http://ilia.ws/archives/216-DevConf-Slides.html" target="_blank">Илью Альшанецкого</a> с докладом об оптимизации работы веб-приложения (PHP и самого вебсервера). Илья не только указал на способы оптимизации но и отдельно остановился на типовых ошибках оптимизации (это в общем-то и была основная тема его доклада). Выступление очень понравилось. Не то чтобы я вынес много нового (но и это было конечно), но получил систематизированный и разложенный по полочкам план по оптимизации.</p>
<p>После я посетил доклад <a href="http://software-testing.ru/" target="_blank">Леши Баранцева</a> о том, почему мы всегда опаздываем с тестированием, который выделялся тематикой на фоне докладов по тем или иным аспектам разработки. Основным пожеланием Алексея к разработчикам в итоге стало следующее: чтобы тестировщики могли качественно протестировать софт, девелоперы должны его отдавать без или практически без дефектов, так как тестирование даже не очень дефектного кода в разы увеличивает длительность/стоимость тестирования или же критически снижает тестовое покрытие (из-за оверхеда на регистрацию и верификацию багов).</p>
<p>После, в ожидании круглого стола (которого в итоге не было), я забрел в главный зал и подремал на докладе Yehuda Katz о Ruby 3 (так как синхроперевод я не взял, а доклад был на английском языке, который у меня не очень fluent). Из-за сдвига по времени я прохлопал основную часть доклада Вадима long Крючкова о демонах на PHP и libevent. Увы и ах.</p>
<p>Потом был обед. Еда была нормальной, но без шведского стола (как на TrainingLabs, где кормят всегда отлично )))</p>
<p>После я сходил на Алекса Дмитриева, который рассказывал про разработку под facebook на rails. Было много про facebook и немного про rails. Увы, доклад был рассчитан на тех кто под FB не писал вообще, поэтому ничего полезного не узнал. В целом доклад был так себе (ой, а я что-то похожее хотел на PHPConf&#8217;09 рассказывать&#8230; чую у меня бы получилось не лучше).</p>
<p>Затем я отправился на доклад Максима Тимохина про REST контроллер. Зачем понадобился еще один фреймворк &#8211; я так и не понял, но пусть будет. В веб-разработке кто не писал свой фреймворк, не полноценный разработчик (что там говорил Альшанецкий про изобретение колес?!) ))) Надо будет скачать его и попробовать чтоли.</p>
<p>Заключительный доклад Георгия Туревича о плюшках PHP5.3 и о том как они используются в ZF2, Doctrine2, Symfony2. Очень познавательный доклад со большим количеством кода на экране ) Надо будет поиграться с Late Static Bindings на досуге. Да и со второй симфонией. Документацию то я перевел, но глобального понимания и просветления не достиг.</p>
<p>Вот такой вот эвент ) Масса интересного народа, интересных докладов. Организаторам как всегда респект )</p>
<p>После официальной программы разливали пиво и терлись разговоры за жизнь в кулуарах ) Немного подмочил завершение вечера ливень, который хлынул когда участники начали расходиться, но с другой стороны не велика беда ))</p>
<p>P.S. Фото будут отдельным постом.</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/05/18/devconf-2010/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>i18n данные в mysql</title>
		<link>http://hudson.su/2010/05/12/i18n-dannye-v-mysql/</link>
		<comments>http://hudson.su/2010/05/12/i18n-dannye-v-mysql/#comments</comments>
		<pubDate>Wed, 12 May 2010 06:07:59 +0000</pubDate>
		<dc:creator>hudson</dc:creator>
				<category><![CDATA[Профессиональное]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://hudson.su/?p=1493</guid>
		<description><![CDATA[Полезный пост от Жени Бабина: http://discover-symfony.blogspot.com/2010/05/symfony-i18n-over-mysql.html. Рассказывается о том как XLIFF переводы (текст в шаблонах) хранить в MySQL. По образу и подобию можно воспользоваться gettext или SQLite. В принципе можно и свой адаптер написать. Спасибо, Женя )]]></description>
			<content:encoded><![CDATA[<p>Полезный пост от Жени Бабина: <a href="http://discover-symfony.blogspot.com/2010/05/symfony-i18n-over-mysql.html" target="_blank">http://discover-symfony.blogspot.com/2010/05/symfony-i18n-over-mysql.html</a>.</p>
<p>Рассказывается о том как XLIFF переводы (текст в шаблонах) хранить в MySQL. По образу и подобию можно воспользоваться gettext или SQLite. В принципе можно и свой адаптер написать.</p>
<p>Спасибо, Женя )</p>
]]></content:encoded>
			<wfw:commentRss>http://hudson.su/2010/05/12/i18n-dannye-v-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

