<?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>fxposter&#039;s wave &#187; Symfony</title>
	<atom:link href="http://blog.fxposter.org/tag/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.fxposter.org</link>
	<description>Stories about Ruby, JavaScript, Objective-C and other cool tools</description>
	<lastBuildDate>Fri, 27 Aug 2010 07:38:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Ressurection</title>
		<link>http://blog.fxposter.org/2010/05/02/ressurection/</link>
		<comments>http://blog.fxposter.org/2010/05/02/ressurection/#comments</comments>
		<pubDate>Sun, 02 May 2010 00:04:15 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[macbook]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=766</guid>
		<description><![CDATA[Настало время возродить этот блог. За более чем полугодие на нем не появилось ни одной статьи и я наконец-то намерен прекратить этот &#8220;застой&#8221;. Да, по сравнению с временами, которые были раньше у меня стало существенно меньше времени, чтобы писать что-то большое и серьезное - работа, университет (если быть точнее - то написание диплома) и еще [...]]]></description>
			<content:encoded><![CDATA[<p>Настало время возродить этот блог. За более чем полугодие на нем не появилось ни одной статьи и я наконец-то намерен прекратить этот &#8220;застой&#8221;. Да, по сравнению с временами, которые были раньше у меня стало существенно меньше времени, чтобы писать что-то большое и серьезное - работа, университет (если быть точнее - то написание диплома) и еще один &#8220;секретный сайд проект&#8221; о котором, возможно, я когда-нибудь всем расскажу.</p>
<p>Начну с глобальных изменений, которые произошли за последнее время в моей жизни и которые однозначно коснутся этого блога.</p>
<p>Ну, во-первых, я теперь не пишу на PHP. Вообще не пишу. И не очень сильно слежу за последними веяниями моды, связанными с этим языком. Да, я все равно иногда появляюсь в группе симфонистов (кому нужен доступ туда - пишите, там новичков любят и на многие нубские вопросы отвечают :) ). Да, я иногда посматриваю на фреймворки, которые сейчас являются популярными в сфере PHP - всякие Yii, ZF, etc. Посматриваю исключительно для того, чтобы быть в курсе происходящего. Учить их и писать на них в общем-то не очень хочется.</p>
<p>На что я променял PHP? Естественно на <a href="http://www.ruby-lang.org/">Ruby</a>. Я не восхищаюсь этим языком, не превозношу его над остальными, просто на работе я пишу на нем (кстати, я работаю над стартапом для бизнесов - <a href="http://waysgo.com/">WaysGo</a>, запуск будет, я надеюсь, очень скоро) и ни на чем другом желания писать особо не возникает - с точки зрения веб-разработки Ruby меня полностью устраивает. Этот язык удобен и достаточно экспрессивен. А <a href="http://rubyonrails.org/">Ruby On Rails</a> - отличное средство для тех, кто хочет писать веб-приложения. Ну, в общем, вы меня поняли. ;)</p>
<p>Кстати говоря, я немного соврал насчет того, что я пишу на Ruby на работе. С начала этой недели я пишу iPhone-приложение на <a href="http://ru.wikipedia.org/wiki/Objective-C">Objective-C</a> и, в связи с этим, шустренько осваиваю Mac, Xcode, сам Objective-C и всякую прочую фигню, которая нужна для разработки под iPhone. Определенного мнения по поводу мака я пока сказать не могу, а вот Objective-C с первого подхода отличается похожестью на руби с точки зрения вызовов методов у объектов и открытых классов, но в то же время отличается несколько некрасивым синтаксисом (квадратные скобки, рррррр). С другой стороны, к синтаксису Ruby у меня тоже изначально было плохое отношение. Это отношение, кстати, не изменилось - я по прежнему считаю, что Ruby - непонятный язык для новичка, и если код на, например, Python можно просто читать, то для того, чтобы почитать код на Ruby придется сначала посмотреть туториалы, или что-то в этом роде, потому что синтаксис кроме выразительности отличается еще и неочевидностью. После пары дней работы с Ruby проблемы отпадают сами собой, так что этот аспект меня уже не очень беспокоит. Собственно, я надеюсь, что рано или поздно я перестану замечать синтаксис Objective-C и буду просто писать код, который делает что мне нужно.</p>
<p>Вот, собственно, и все на сегодня. Вроде ничего не забыл. До скорого! :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2010/05/02/ressurection/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Symfony 2.0 Presentation</title>
		<link>http://blog.fxposter.org/2009/03/10/symfony-20-presentation/</link>
		<comments>http://blog.fxposter.org/2009/03/10/symfony-20-presentation/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 22:45:49 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=686</guid>
		<description><![CDATA[В сообществе симфонистов праздник - Фабьен наконец-то рассказал о том, что можно ожидать от следующей мажорной версии фреймворка: IOC-контейнер В презентации это называлось Dependency Injection Container. Подробнее о том, что это такое можно узнать в википедии: IOC, Dependency Injection. Либо спросите знакомых Java EE программистов, они должны знать, что это такое. :) За примерами лучше, [...]]]></description>
			<content:encoded><![CDATA[<p>В сообществе симфонистов праздник - Фабьен наконец-то <a href="http://fabien.potencier.org/talk/22/phpquebec-2009-symfony-2">рассказал</a> о том, что можно ожидать от следующей мажорной версии фреймворка:</p>
<h3>IOC-контейнер</h3>
<p>В презентации это называлось Dependency Injection Container. Подробнее о том, что это такое можно узнать в википедии: <a href="http://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D1%89%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8F">IOC</a>, <a href="http://ru.wikipedia.org/wiki/Dependency_Injection">Dependency Injection</a>. Либо спросите знакомых Java EE программистов, они должны знать, что это такое. :) За примерами лучше, опять же, обращаться к Java: <a href="http://www.picocontainer.org/introduction.html">Pico Container Introduction</a> (достаточно просто и понятно), <a href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html">Spring IOC-container</a>. Вкратце - скармливаем контейнеру классы и зависимости между ними и можем строить новые обьекты, которые будут построены на этих зависимостях (если у вам один обьект зависит от двух других, то они будут в него автоматически вставлены - через конструктор, методы, свойства, etc.). На PHP я IOC-контейнера ни разу не видел (хотя они есть) и&#8230; Не знаю, насколько он будет действительно удобен и нужен. Будем смотреть.</p>
<h3>Новый шаблонный движок</h3>
<p>Лучше смотреть презентацию - всё полностью переписано, много новых возможностей: шаблоны теперь не только file-based, но и memory-based (memcache, apc), database-based и т.д, появилось наследование шаблонов (привет, Django), все возможности предыдущих версий (типа partials, slots), думаю, останутся. Всё это будет приправлено отсутствием зависимостей от самой Symfony (как я понимаю, под &#8220;Independent library&#8221; они имеют ввиду именно это).</p>
<h3>sfRequestHandler</h3>
<p>Коротко и ясно - &#8220;Rails Metal in Symfony&#8221;.</p>
<p>Кстати говоря, довольно интересен тот факт, что засуетились все только сейчас, а ведь это не первая презентация о возможностях, которые нам приподнесут в Symfony 2.0 - на Symfony Camp 2008 об этом уже <a href="http://fabien.potencier.org/talk/17/symfony-camp-2008-beyond-1-2">говорили</a>. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2009/03/10/symfony-20-presentation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>&#8220;Скрытые&#8221; записи с Symfony и Doctrine</title>
		<link>http://blog.fxposter.org/2009/02/07/hidden-records-with-symfony-and-doctrine/</link>
		<comments>http://blog.fxposter.org/2009/02/07/hidden-records-with-symfony-and-doctrine/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 06:24:14 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=663</guid>
		<description><![CDATA[Под &#8220;скрытыми&#8221; записями сегодня будут пониматься &#8220;unapproved&#8221;-записи в таблице. Кому лень ходить по сылкам: иногда не все записи какой-нибудь таблицы нужно показывать пользователю, например - если я не хочу показывать некоторые посты в блоге. Обычно для этого я делаю поле, например, is_hidden, а затем выбираю все записи, где is_hidden = 0. Проблема состоит в том, [...]]]></description>
			<content:encoded><![CDATA[<p>Под &#8220;скрытыми&#8221; записями сегодня будут пониматься <a href="http://blog.fxposter.org/2008/02/02/approved-and-unapproved-records/">&#8220;unapproved&#8221;</a>-записи в таблице. Кому лень ходить по сылкам: иногда не все записи какой-нибудь таблицы нужно показывать пользователю, например - если я не хочу показывать некоторые посты в блоге. Обычно для этого я делаю поле, например, is_hidden, а затем выбираю все записи, где is_hidden = 0. Проблема состоит в том, что я обычный человек и могу забыть поставить нужное мне условие. Поэтому я хочу получить какое-нибудь простое, но очень эффективное решение такой проблемы. В ActiveRecord этим решением является default_scope. А я вам сегодня расскажу, как этого добиться в Doctrine.</p>
<p>Итак, представим, что у нас есть табличка Post:</p>
<pre><code class="yaml">Post:
  actAs:
    Timestampable: ~
  columns:
    title:     { type: string(128), notnull: true }
    text:      { type: text, notnull: true }
    is_hidden: { type: boolean, notnull: true, default: 0 }</code></pre>
<p>Самый простой, на первый взгляд, подход - переопределять <code class="php">PostTable::createQuery()</code>, чтобы этот метод возвращал уже Query с нужным нам &#8220;WHERE is_hidden = 0&#8243;. К сожалению, не всегда это помогает. Например, при выборке постов для какой-либо категории через $category-&gt;Posts этот метод не сработает.</p>
<p>Есть гораздо более простой способ сделать то, что нам нужно - использовать <a href="http://www.doctrine-project.org/documentation/manual/1_0/en/one-page#event-listeners">listener-ы</a>. В Doctrine есть довольно много событий, которые мы можем &#8220;слушать&#8221; и на которые мы можем реагировать. В данном случае нам подходит событие &#8220;preDqlSelect&#8221;, которое входит в группу &#8220;<a href="http://www.doctrine-project.org/documentation/manual/1_0/en/one-page#event-listeners:dql-hooks">DQL Hooks</a>&#8220;, и которое вызывается перед выполнением запроса на выборку записей. Как нам нужно прореагировать на событие: взять Doctrine_Query из Doctrine_Event и добавить в него дополнительные условия выборки.</p>
<p>Самый простой способ - переопределить метод preDqlSelect в самой записи:</p>
<pre><code class="php">class Post extends BasePost
{
  public function preDqlSelect(Doctrine_Event $event)
  {
    $params = $event-&gt;getParams();
    $event-&gt;getQuery()-&gt;addWhere("{$params['alias']}.is_hidden = 0");
  }
}</code></pre>
<p>В первой строке метода мы получаем параметры запроса, из которых нам нужен alias - можете считать это обычным alias-ом таблицы из SQL (в данном случае это alias таблицы в DQL), т.е. при таком DQL:</p>
<pre><code class="dql">FROM Post p</code></pre>
<p>alias-ом будет &#8220;p&#8221;.</p>
<p>Во второй строке мы получаем текущую query и добавляем в неё условие &#8220;is_hidden = 0&#8243;.</p>
<p class="note">Мы не можем использовать <code class="php">-&gt;where()</code>, т.к. этот метод сотрет все имеющиеся части WHERE в запросе. В то же время <code class="php">-&gt;addWhere</code> и <code class="php">-&gt;andWhere</code> ведут себя так же, как и <code class="php">-&gt;where</code> при отсутствии where-части запроса.</p>
<p>Собственно, вот и всё - тепер у нас будут выбираться только &#8220;видимые&#8221; посты.</p>
<p><em>Во второй части будет показано, как сделать созданный в этом посте код более реюзабельным, а также как сделать так, чтобы в backend-е посты показывались полностью.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2009/02/07/hidden-records-with-symfony-and-doctrine/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Doctrine admin generator + sfDoctrineGuardPlugin + disabled security = bug</title>
		<link>http://blog.fxposter.org/2009/01/31/doctrine-admin-generator-sfdoctrineguardplugin-disabled-security-bug/</link>
		<comments>http://blog.fxposter.org/2009/01/31/doctrine-admin-generator-sfdoctrineguardplugin-disabled-security-bug/#comments</comments>
		<pubDate>Sat, 31 Jan 2009 05:53:37 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Symfony Plugins]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=646</guid>
		<description><![CDATA[Есть в Symfony такая штука, как генератор админки на основании описанных моделей. Подробно о самом генераторе админки лучше читать здесь (кстати, я не понял, а про propel:generate-module теперь в Symfony Book не рассказывается ничего, что ли?). Я вчера столкнулся с багом, который ошибочно описал здесь, а затем правильно - здесь. Кто не хочет читать мой [...]]]></description>
			<content:encoded><![CDATA[<p>Есть в Symfony такая штука, как генератор админки на основании описанных моделей. Подробно о самом генераторе админки лучше читать <a href="http://www.symfony-project.org/book/1_2/14-Generators">здесь</a> (кстати, я не понял, а про propel:generate-module теперь в Symfony Book не рассказывается ничего, что ли?).</p>
<p>Я вчера столкнулся с багом, который ошибочно описал <a href="http://trac.symfony-project.org/ticket/5738">здесь</a>, а затем правильно - <a href="http://trac.symfony-project.org/ticket/5746">здесь</a>. Кто не хочет читать мой кривой английский - читаем дальше. Баг воспроизводится при наличии трех условий:</p>
<ol>
<li>класс myUser наседуется от sfGuardSecurityUser из плагина sfDoctrineGuardPlugin</li>
<li>для всего приложения (или только для модуля админки) отключена проверка безопасности (is_secure: off, в общем)</li>
<li>пользователь не авторизован</li>
</ol>
<p>В этом случае вы получите вот это сообщение:</p>
<blockquote><p>You don&#8217;t have the required permission to access this page.</p></blockquote>
<p>Решение описано в <a href="http://trac.symfony-project.org/ticket/5738">первом моём тикете</a>:</p>
<blockquote><p>Нужно заменить в файле &#8220;&lt;путь к библиотекам symfony&gt;/lib/plugins/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/actions/actions.class.php&#8221; (это шаблоны для генератора админки Doctrine) эти строки:</p>
<pre><code class="php">if (!$this-&gt;getUser()-&gt;hasCredential($this-&gt;configuration-&gt;getCredentials($this-&gt;getActionName())))
{
  $this-&gt;forward(sfConfig::get('sf_secure_module'), sfConfig::get('sf_secure_action'));
}</code></pre>
<p>на эти:</p>
<pre><code class="php">credentials = $this-&gt;configuration-&gt;getCredentials($this-&gt;getActionName());
if (!empty($credentials) &amp;&amp; !$this-&gt;getUser()-&gt;hasCredential($credentials))
{
  $this-&gt;forward(sfConfig::get('sf_secure_module'), sfConfig::get('sf_secure_action'));
}</code></pre>
</blockquote>
<p>Баг некритичный, так что можно, в принципе, от него не избавляться, а подождать, пока изменения внесут в главный репозиторий. Просто если встретите его - не удивляйтесь. Лично я долго не мог понять - почему у меня не работает is_secure: off.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2009/01/31/doctrine-admin-generator-sfdoctrineguardplugin-disabled-security-bug/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Doctrine</title>
		<link>http://blog.fxposter.org/2009/01/31/doctrine/</link>
		<comments>http://blog.fxposter.org/2009/01/31/doctrine/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 23:33:21 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=639</guid>
		<description><![CDATA[Последнюю неделю работаю с Symfony 1.2 и Doctrine. Так вот, если раньше я хвалил Doctrine, то теперь&#8230; В общем, после нескольких дней работы с ней захотелось плеваться&#8230; На первый взгляд всё замечательно, но как только начинаешь копать глубже начинается ужас. Мне очень не хочется рассказывать про эти баги и недоделки (причина банальна - просто лень [...]]]></description>
			<content:encoded><![CDATA[<p>Последнюю неделю работаю с <a href="http://www.symfony-project.org/">Symfony 1.2</a> и <a href="http://www.doctrine-project.org/">Doctrine</a>. Так вот, если раньше я <a href="http://blog.fxposter.org/2008/02/06/propel/">хвалил Doctrine</a>, то теперь&#8230; В общем, после нескольких дней работы с ней захотелось плеваться&#8230; На первый взгляд всё замечательно, но как только начинаешь копать глубже начинается ужас. Мне очень не хочется рассказывать про эти баги и недоделки (причина банальна - просто лень вспоминать, выискивать по истории icq/jabber о всех багах, которые я нашел). У меня было не очень хорошее впечатление о Propel, но, по крайней мере, когда я работал с ним, у меня была уверенность, что всё будет работать и ничего не сломается, если я что-то добавлю/изменю. С Doctrine такой уверенности лично у меня нет (хотя коллеги тут подсказывают, что всё наладится :)) - такое впечатление, что &#8220;еще чуть-чуть&#8221; - и все развалится. Это мнение исключительно субьективное, обьяснять я его не буду, если кто-то что-то желает узнать - прошу в icq/jabber, все контакты есть в сайдбаре моего блога.</p>
<p>Напоследок всё-же хочется привести пример одной из &#8220;недоделок&#8221;, которую при хорошем коде можно было бы легко исправить:</p>
<p>Имеем следующий код:</p>
<pre><code class="php">// Category has many Posts
$category = Doctrine::getTable('Category')-&gt;find(1);
$posts = $category-&gt;Posts;</code></pre>
<p>Задача состоит в том, чтобы в $posts были посты, отсортированным по какому-нибудь полю бд. Причем, естественно, хочется, чтобы посты были отсортированы не только про вот такой их выборке через LazyLoading, но и при Eager Loading, т.е.:</p>
<pre><code class="php">$category = Doctrine::getTable('Category')-&gt;createQuery('c')-&gt;leftJoin('c.Posts')-&gt;fetchOne(); // выборка всех данных одним запросом
$posts = $category-&gt;Posts; // запроса к бд не проиходит</code></pre>
<p>На самом деле, про Eager Loading я с самого начала не думал, но, я думаю, со мной никто спорить не будет, что если сортировка должна быть в одном случае - она обязанна быть и во втором.</p>
<p>Так вот - эту проблему в доктрине приходится решать вручную для каждого поля, причем кешование данных тоже приходится хендлить самому.</p>
<p>При вызове свойства <code class="php">$category-&gt;Posts</code>, будет вызываться метод <code class="php">$category-&gt;getPosts()</code>, который мы и будем переопределять:</p>
<pre><code class="php">class Category extends BaseCategory
{
  public function getPosts() // в идеале сюда должен передаваться параметр $load, но пока о нем забудем
  {
    return Doctrine::getTable('Post')
        -&gt;createQuery()
          -&gt;orderBy('column ASC')
          -&gt;where('category_id = ?', $this-&gt;id)
        -&gt;execute();
  }
}</code></pre>
<p>Красиво? Как по мне - не очень, т.к. несмотря на наличие уже указанной связи - использовать её я не могу, приходится строить query заново.</p>
<p>Возможно, связью я воспользоваться могу, об этом нужно подумать&#8230; Пока писал пост пришла в голову идея, но проверять лень.</p>
<p>Запускаем. Пробуем:</p>
<pre><code class="php">$category = Doctrine::getTable('Category')-&gt;find(1);
$posts = $category-&gt;Posts;
$posts = $category-&gt;Posts;
$posts = $category-&gt;Posts;
$posts = $category-&gt;Posts;</code></pre>
<p>И что мы видим? 5 запросов к бд. Хмм. Убираем метод <code class="php">getPosts</code>. Запускаем тот же код. В итоге - два запроса. Я, конечно, понимаю, что это я такой плохой и лентяй еще к тому же, но ведь можно было сделать подобное &#8220;кеширование&#8221; для связей автоматически (если кто знает, как это сделать - дайте знать, походя дофига времени по кодам доктрины я не нашел место, где это можно сделать). Ладно, сделаем &#8220;кеширование&#8221;:</p>
<pre><code class="php">public function getPosts()
{
  if (!isset($this-&gt;_references['Posts']))
    $this-&gt;_references['Posts'] = Doctrine::getTable('Post')
        -&gt;createQuery()
          -&gt;orderBy('column ASC')
          -&gt;where('category_id = ?', $this-&gt;id)
        -&gt;execute();
  return $this-&gt;_references['Posts'];
}</code></pre>
<p>Запускаем уже запомнившийся нам код. Ну слава богу - два запроса.</p>
<p>На самом деле нужно еще кое-что переопределять (типа <code>Category::loadReference</code>), но я на это забил, т.к. вряд ли я буду вызывать этот метод вручную. А его вызов системой мне, вроде бы не встречался.</p>
<p>Ну, вроде более-менее готово. По крайней мере - можно пользоваться, а нам только это и нужно.</p>
<p>Теперь об Eager Loading. О нем я сам даже и не вспоминал, т.к. у меня не было ни одной идеи - как его реализовать (нужно было опять копаться в исходниках Doctrine, а это мне уже, порядком, поднадоело). Как вдруг, откуда ни возьмись, появился пост в блоге доктрины: <a href="http://www.doctrine-project.org/blog/cookbook-recipe-relation-dql-behavior">Cookbook Recipe: Relation DQL Behavior</a>. Советую прочесть его и комментарии (благо, их там немного). Вы увидите в комментариях и меня, говорящим спасибо за Eager Loading, а также указавшим на то, что в случае Lazy Loading-а решение не работает. На что мне ответили:</p>
<blockquote><p>You&#8217;re right the above won&#8217;t work, but you shouldn&#8217;t ever be doing that :) You should always load your data through full DQL queries and avoid lazy loading data</p></blockquote>
<p>Ага. Благодарю покорно. Зачем тогда вообще делать Lazy Loading, если его не нужно юзать. Может, мне банально удобнее написать <code class="php">$category-&gt;Posts</code> и получить посты тогда, когда это реально нужно, а не при выборке категории. Да, я получу два запроса вместо одного, ну и что? Это не O(n), а я не привык оптимизировать то, что нормально работает и так.</p>
<p>И напоследок: на самом деле проблему вполне можно было бы решить путем наследования от класса связи и его расширения. Однако сделать это в Doctrine сне не судилось, т.к. в отношениях hasOne, hasMany намертво зашиты стандартные классы связей Doctrine, а жаль. Такие связи - это плохо, т.к. они статичны и не способствуют хорошему расширению системы. С другой стороны - не мне критиковать jwage, самбы я вряд ли сделал что-то подобное, по крайней мере сейчас.</p>
<p><em><strong>PS</strong>. Долго думал, как назвать пост. Так и не придумал&#8230; :(</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2009/01/31/doctrine/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Наследование шаблонов в Symfony</title>
		<link>http://blog.fxposter.org/2008/08/26/template-inheritance-in-symfony/</link>
		<comments>http://blog.fxposter.org/2008/08/26/template-inheritance-in-symfony/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 17:54:36 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Template Inheritance]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=554</guid>
		<description><![CDATA[Вопрос, так, невзначай. Хотели бы вы аналог получить в Symfony аналог наследования шаблонов из Django? PS. Палюсь&#8230; Ой как палюсь. :)]]></description>
			<content:encoded><![CDATA[<p>Вопрос, так, невзначай. Хотели бы вы аналог получить в Symfony аналог наследования шаблонов из Django?</p>
<p><em><strong>PS</strong>. Палюсь&#8230; Ой как палюсь. :)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2008/08/26/template-inheritance-in-symfony/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Наследование шаблонов в Smarty</title>
		<link>http://blog.fxposter.org/2008/08/26/template-inheritance-in-smarty/</link>
		<comments>http://blog.fxposter.org/2008/08/26/template-inheritance-in-smarty/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 10:12:48 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Разное]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Smarty]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[View]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=552</guid>
		<description><![CDATA[На Хабре появилась замечательная статья &#8220;Наследование шаблонов в Smarty&#8220;. Впервые эта штука мне встретилась в Django, теперь вот есть и для Smarty. Посмотрел на систему view в Symfony&#8230; Эх&#8230; Для реализации подобного, навскидку, прийдется довольно сильно переделать внутренности этого фреймворка.]]></description>
			<content:encoded><![CDATA[<p>На Хабре появилась замечательная статья &#8220;<a href="http://habrahabr.ru/blogs/php/37962/">Наследование шаблонов в Smarty</a>&#8220;. Впервые эта штука мне встретилась в Django, теперь вот есть и для Smarty. Посмотрел на систему view в Symfony&#8230; Эх&#8230; Для реализации подобного, навскидку, прийдется довольно сильно переделать внутренности этого фреймворка.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2008/08/26/template-inheritance-in-smarty/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Propel 1.3</title>
		<link>http://blog.fxposter.org/2008/08/20/propel-13/</link>
		<comments>http://blog.fxposter.org/2008/08/20/propel-13/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 19:53:41 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Propel]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=535</guid>
		<description><![CDATA[На днях вышла долгожданная новая версия достаточно популярного в узких кругах ORM - Propel 1.3. Из интересных мне нововведений: В основе Propel 1.3 лежит новый механизм работы с базами данных - PDO, который заменил Creole и привел к ощутимому повышению скорости работы. Теперь не нужно вручную загружать классы Propel и свои модели - теперь это [...]]]></description>
			<content:encoded><![CDATA[<p>На днях вышла долгожданная новая версия достаточно популярного в узких кругах ORM - <a href="http://propel.phpdb.org/trac/wiki/Users/News/Propel1.3.0">Propel 1.3</a>.</p>
<p>Из интересных мне нововведений:</p>
<ul>
<li>В основе Propel 1.3 лежит новый механизм работы с базами данных - <a href="http://php.net/pdo">PDO</a>, который заменил <a href="http://creole.phpdb.org/trac/">Creole</a> и привел к ощутимому повышению скорости работы.</li>
<li>Теперь не нужно вручную загружать классы Propel и свои модели - теперь это делается автоматически (через autoloading в PHP)</li>
<li>“Object Instance Pooling”, или, как его называет небезызвестный Фаулер - Identity Map. Причем, что самое интересное, это работает не только с retrieveByPk(), но и со всему doSelect*()-методами (в зависимости от переданных аргументов), что позволяет ускорить работу засчет отсутствия лишних запросов к бд, а также ненужности построения одинаковых обьектов несколько раз.</li>
<li>Связи один-к-одному теперь поддерживаются нативно (блин, хочу много-ко-многим!)</li>
<li>Куча мелких (и не очень) исправлений и улучшений</li>
</ul>
<p>Поподробнее можно прочитать на <a href="http://redotheweb.com/2008/08/20/propel-13-is-out/">RedoTheWeb</a>, в также на <a href="http://propel.phpdb.org/trac/wiki/Users/Documentation/1.3/Upgrading">офсайте Propel</a>.</p>
<p><em><strong>PS</strong>. Сам еще не юзал, но нужно будет попробовать. На мой взгляд, самый интересный момент связан с тем, можно ли переопределить фетчинг записей, например - выбирать только записи с <code>is_hidden = false</code>, да так, чтобы переопределять пришлось только одну функцию.</em></p>
<p><strong>Update</strong>: Как написали на <a href="http://www.symfony-project.org/blog/2008/08/21/propel-1-3-doctrine-1-0-and-symfony-1-2">официальном блоге Symfony</a> - &#8220;Object Instance Pooling is not an Identity Map because the database request is still needed&#8221;. Нужно будет изучить этот вопрос.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2008/08/20/propel-13/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Клич использующим Symfony</title>
		<link>http://blog.fxposter.org/2008/08/17/for-users-of-symfony/</link>
		<comments>http://blog.fxposter.org/2008/08/17/for-users-of-symfony/#comments</comments>
		<pubDate>Sat, 16 Aug 2008 22:36:54 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=530</guid>
		<description><![CDATA[Если вы используете Symfony, планируете это делать или просто интересуетесь этим фреймворком - значит нам нужно поговорить. Мои контакты: ICQ: 625585 Jabber: fxposter@gmail.com Skype: fxposter]]></description>
			<content:encoded><![CDATA[<p>Если вы используете Symfony, планируете это делать или просто интересуетесь этим фреймворком - значит нам нужно поговорить. Мои контакты:</p>
<ul>
<li>ICQ: 625585</li>
<li>Jabber: fxposter@gmail.com</li>
<li>Skype: fxposter</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2008/08/17/for-users-of-symfony/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Symfony 1.1</title>
		<link>http://blog.fxposter.org/2008/07/20/symfony-11/</link>
		<comments>http://blog.fxposter.org/2008/07/20/symfony-11/#comments</comments>
		<pubDate>Sat, 19 Jul 2008 22:35:28 +0000</pubDate>
		<dc:creator>fxposter</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Работа]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.fxposter.org/?p=470</guid>
		<description><![CDATA[Собственно, о том, что вышла Symfony 1.1 писали многие, и вы об этом наверняка уже слышали. Но для тех, кто об этом еще не знает, повторю нововведения, а также выскажу о них своё [авторитетное :)] мнение: Новая архитектура. Явное улучшение - компоненты теперь меньше зависят друг от друга. Новая система конфигурирования. К счастью, конфигурация через [...]]]></description>
			<content:encoded><![CDATA[<p>Собственно, о том, что <a href="http://www.symfony-project.org/blog/2008/06/30/the-wait-is-over-symfony-1-1-released">вышла Symfony 1.1</a> писали многие, и вы об этом наверняка уже слышали. Но для тех, кто об этом еще не знает, повторю нововведения, а также выскажу о них своё [авторитетное :)] мнение:</p>
<ul>
<li><a href="http://www.symfony-project.org/blog/2008/06/23/the-symfony-1-1-architecture">Новая архитектура</a>. Явное улучшение - компоненты теперь меньше зависят друг от друга.</li>
<li>Новая система конфигурирования. К счастью, конфигурация через YAML-файлы никуда не делась. Просто сама структура конфигов переделана.</li>
<li>&#8220;The new object-oriented <a class="ext-link" href="http://www.symfony-project.org/book/forms/1_1/">form framework</a>&#8220;. Звучит действительно круто. А смысл такой - генерация форм динамически, вместо статических хелперов (которые, кстати, остались), а также - вся работа с формами (указание полей, их валидаторов, настройка свойств показа формы и прочее)  теперь делается в одном месте, что очень удобно. Есть интеграция форм с Propel, например - автоматическая генерация форм по модели.</li>
<li>Новая <a href="http://www.symfony-project.org/cookbook/1_1/en/tasks">система консольных комманд</a>. Честно сказать - если вы не разрабатываете плагины, то разницу вы увидите только в том, что некоторые комманды поменяли своё название.</li>
<li>Новый <a href="http://www.symfony-project.org/blog/2008/06/19/yaml-in-symfony-1-1">парсер YAML</a>. Разве что изменили выдачу инфы об ошибках. Ну и кое-что добавили. Как по мне - для конечного девелопера разница очень мала.</li>
<li>Теперь плагины - это обычные пакеты PEAR, со всеми вытекающими последствиями, из которых главным, на мой взгляд, является возможность указаниязависимостей от других плагинов.</li>
<li> Теперь можно выдавать различные вьюхи в зависимости от того, какоt значение принимает хедер Accept. Поподробнее - <a href="http://www.symfony-project.org/cookbook/1_1/en/iphone">здесь</a>.</li>
<li>Собствено, ORM теперь полностью вынесен в плагины. Symfony 1.0 содержала в себе Propel 1.2, и была возможность заменить его на Propel 1.3/Doctrine через плагины. Теперь же и Propel 1.2 вынесен в отдельный плагин. Скорее всего эта возможность пришла вследствии пункта №1.</li>
<li>Для того, чтобы приложения, написанные на Symfony 1.0 запускались на версии 1.1 был сделан sfCompat10Plugin, который, насколько я понял, в версии 1.2 уберут совсем. К сожалению, проекты всё таки прийдется дорабатывать, чтобы они работали на Symfony 1.1, подробнее об этом можно прочесть <a href="http://svn.symfony-project.com/branches/1.1/UPGRADE">здесь</a>.</li>
<li> Переписан класс routing&#8217;а. Теперь все пути кешируются + от этого класса можно отнаследоваться и переделать, от чего бы я <a href="http://blog.fxposter.org/2008/03/21/regexp/">не отказался</a>.</li>
</ul>
<p>А теперь посмотрите и скажите - что из этого может реально пригодится? ИМХО:</p>
<ul>
<li>Form Framework</li>
<li>Зависимости в плагинах</li>
<li>Различные вьюхи в зависимости от того, какоt значение принимает хедер Accept</li>
</ul>
<p>Причем последние два пункта лично я пока не использовал бы нигде. Просто нет необходимости. К чему это я клоню - этот релиз чуть ли не официально был признан &#8220;промежуточным&#8221; - минимум новых интересных фич и очень сильная переработка кода, причем зачастую внутреннего, для облегчения дальнейшей поддержки и добавления новых фич в будущем. В частности - в версии 1.2 нововведений меньше, но они гораздо больше коснуться конечных пользователей фреймворка (коснуться - в хорошем смысле). Кстати говоря, версия 1.2 выйдет уже в октябре, через 3 месяца&#8230; Но это уже несколько друга история, о которой мы поговорим, скорее всего завтра.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fxposter.org/2008/07/20/symfony-11/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
