<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10frenchfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="fr"><title type="text">Prendre un Café</title><link rel="alternate" type="text/html" href="http://prendreuncafe.com/blog/" /><rights type="text">Contenus sous licence Creative Commons BY-SA</rights><updated>1970-01-01T00:00:00+00:00</updated><generator>Dotclear</generator><subtitle type="html">... le blog de comptoir.</subtitle><geo:lat>48.801479</geo:lat><geo:long>2.326462</geo:long><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-sa/2.0/" /><logo>http://www.prendreuncafe.com/blog/images/rss_head.jpg</logo><link rel="self" href="http://feeds.feedburner.com/prendreuncafe" type="application/atom+xml" /><feedburner:emailServiceId>prendreuncafe</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><title type="text">An Interactive PHP Shell: phpsh</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/K5v6KyfYRdo/An-Interactive-PHP-Shell%3A-PHPSH" /><category term="Dev" /><category term="cli" /><category term="php" /><category term="shell" /><category term="symfony" /><author><name>NiKo</name></author><updated>2009-11-04T03:00:00-08:00</updated><id>urn:md5:632f3830bb8da94e1293d0cedff337a5</id><content type="html">&lt;p&gt;Just found this nice project contributed by the Facebook team, &lt;a href="http://www.phpsh.org/" hreflang="en"&gt;phpsh&lt;/a&gt;. Basically, it&amp;#8217;s an interactive and advanced command line interface to &lt;a href="http://php.net/"&gt;php&lt;/a&gt;, a kind of super-&lt;code&gt;php -r&lt;/code&gt; similar to what you can find in &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; or &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;. Ironically enough, phpsh is mostly written in Python, by the way.&lt;/p&gt;


&lt;p&gt;To install phpsh, just get it from github&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH#pnote-1128-1" id="rev-pnote-1128-1"&gt;1&lt;/a&gt;]&lt;/sup&gt;:&lt;/p&gt;

&lt;pre&gt;
$ git clone git://github.com/facebook/phpsh.git
$ cd phpsh
$ python setup.py build
$ sudo python setup.py install
&lt;/pre&gt;


&lt;p&gt;To run phpsh:&lt;/p&gt;

&lt;pre&gt;
$ phpsh
Starting php
type 'h' or 'help' to see instructions &amp;amp; features
php&amp;gt; =&amp;quot;hello world&amp;quot;
hello world
php&amp;gt; =2 + 2
4
php&amp;gt; $a = 8

php&amp;gt; =$a
8
&lt;/pre&gt;


&lt;p&gt;Note that you don&amp;#8217;t have to open or close &lt;code&gt;&amp;lt;?php&lt;/code&gt; tags, you can print something just by prepending an &lt;code&gt;=&lt;/code&gt; sign to the command, and no need to type semicolum at the end of a call. Easy&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH#pnote-1128-2" id="rev-pnote-1128-2"&gt;2&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;p&gt;You can access a function documentation by just prepending the &lt;code&gt;d&lt;/code&gt; keyword to its name:&lt;/p&gt;

&lt;pre&gt;php&amp;gt; d strlen
&amp;nbsp;
# strlen
&amp;nbsp;
(PHP 4, PHP 5)
&amp;nbsp;
strlen -- Get string length
&amp;nbsp;
### Description
&amp;nbsp;
int strlen ( string $string )
&amp;nbsp;
Returns the length of the given string . 
&amp;nbsp;
### Parameters
&amp;nbsp;
string     
&amp;nbsp;
The [string][1] being measured for length. 
&amp;nbsp;
### Return Values
&amp;nbsp;
The length of the string on success, and 0 if the string is empty. 
&amp;nbsp;
### 
&amp;nbsp;
   [1]: #language.types.string&lt;/pre&gt;


&lt;p&gt;You can define your own classes and functions, and run them:&lt;/p&gt;

&lt;pre&gt;
php&amp;gt; function foo($a){echo $a.'!';}
php&amp;gt; foo('bar')
bar!
&lt;/pre&gt;


&lt;p&gt;Same goes for classes:&lt;/p&gt;

&lt;pre&gt;
php&amp;gt; class Foo {public function bar($a){echo $a.'!';}}
php&amp;gt; $f = new Foo()
php&amp;gt; $f-&amp;gt;bar('baz')
baz!
&lt;/pre&gt;


&lt;p&gt;You can even execute shell command from there:&lt;/p&gt;

&lt;pre&gt;
php&amp;gt; ! ls -la
&lt;/pre&gt;


&lt;p&gt;Of course, you can &lt;del&gt;import&lt;/del&gt; include and require files. As a concrete example, let&amp;#8217;s roughly play with the symfony API:&lt;/p&gt;

&lt;pre&gt;
php&amp;gt; ! symfony -V
symfony version 1.2.2-DEV (/Users/niko/Sites/vendor/symfony12/lib)
php&amp;gt; c /Users/niko/Sites/vendor/symfony12/lib/autoload/sfCoreAutoload.class.php
Extra includes are: ['/Users/niko/Sites/vendor/symfony12/lib/autoload/sfCoreAutoload.class.php']
php&amp;gt; sfCoreAutoload::register()
php&amp;gt; =sfYaml::load('foo: bar')
array(
  &amp;quot;foo&amp;quot; =&amp;gt; &amp;quot;bar&amp;quot;,
)
php&amp;gt; =sfYaml::dump(array('foo' =&amp;gt; array('bar' =&amp;gt; 'baz')))
&amp;quot;foo:\n  bar: baz\n&amp;quot;
&lt;/pre&gt;


&lt;p&gt;Last but not least, when enough playing, type &lt;code&gt;q&lt;/code&gt; or press &lt;code&gt;ctrl + d&lt;/code&gt; to quit phpsh.&lt;/p&gt;
&lt;div class="footnotes"&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH#rev-pnote-1128-1" id="pnote-1128-1"&gt;1&lt;/a&gt;] So yeah, so you need &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt;. And Python, of course.&lt;/p&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH#rev-pnote-1128-2" id="pnote-1128-2"&gt;2&lt;/a&gt;] Anybody putting &amp;quot;rather use python then&amp;quot; will have serious troubles, even if I strongly agree.&lt;/p&gt;&lt;/div&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH"&gt;An Interactive PHP Shell: phpsh&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/K5v6KyfYRdo" height="1" width="1"/&gt;</content><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH#comment-form</wfw:comment><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://prendreuncafe.com/blog/feed/atom/comments/1128</wfw:commentRss><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/11/04/An-Interactive-PHP-Shell%3A-PHPSH</feedburner:origLink></entry><entry><title type="text">A Symfony 1.3 Gem: Open Files Listed in Exceptions with the Editor of your Choice</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/9oVIXMg4oIw/A-Symfony-1.3-Gem%3A-Open-Files-Listed-in-Exceptions-with-the-Editor-of-your-Choice" /><category term="Dev" /><category term="editor" /><category term="php" /><category term="symfony" /><category term="textmate" /><author><name>NiKo</name></author><updated>2009-10-12T09:22:00-07:00</updated><id>urn:md5:6781e6a12d91dda46f4bd533e7f180ac</id><content type="html">&lt;p&gt;I&amp;#8217;ve just stumbled upon a nice new feature of &lt;a href="http://www.symfony-project.org/" hreflang="en"&gt;Symfony&lt;/a&gt; 1.3, the ability to &lt;a href="http://www.symfony-project.org/tutorial/1_3/en/whats-new#chapter_64a8dd2fac010cece60fe956d341725f_sub_sf_file_link_format" hreflang="en"&gt;open any linked file within standard exception page with the text editor of your choice&lt;/a&gt;, at least if it provides an url scheme/protocol to open them. &lt;a href="http://blog.macromates.com/2007/the-textmate-url-scheme/" hreflang="en"&gt;Texmate provides natively this feature&lt;/a&gt;, so let&amp;#8217;s see how to configure a symfony project to allow its files to be opened directly in textmate when encountering a stack trace.&lt;/p&gt;


&lt;p&gt;In the &lt;code&gt;config/&lt;/code&gt; folder of the project, create a &lt;code&gt;settings.yml&lt;/code&gt; file with this content:&lt;/p&gt;

&lt;pre&gt;dev: #yeah, we never know
  .settings:
    file_link_format: &amp;quot;txmt://open?url=file://%f&amp;amp;line=%l&amp;quot;&lt;/pre&gt;


&lt;p&gt;That&amp;#8217;s it. Now any standard exception page (in &lt;code&gt;dev&lt;/code&gt; environment only, right?) will provide a &lt;code&gt;txmt://&lt;/code&gt; link to every PHP file listed in the stack trace. And at the correct line number. Neat.&lt;/p&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/10/12/A-Symfony-1.3-Gem%3A-Open-Files-Listed-in-Exceptions-with-the-Editor-of-your-Choice"&gt;A Symfony 1.3 Gem: Open Files Listed in Exceptions with the Editor of your Choice&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/9oVIXMg4oIw" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/10/12/A-Symfony-1.3-Gem%3A-Open-Files-Listed-in-Exceptions-with-the-Editor-of-your-Choice</feedburner:origLink></entry><entry><title type="text">Scrum.py, présentation et conférence Scrum et Python le 23 octobre à Montpellier</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/zX1wsd7psTg/Scrum.py%2C-pr%C3%A9sentation-et-conf%C3%A9rence-Scrum-et-Python-le-23-octobre-%C3%A0-Montpellier" /><category term="Divers" /><category term="django" /><category term="montpellier" /><category term="python" /><category term="scrum" /><author><name>NiKo</name></author><updated>2009-10-12T03:17:00-07:00</updated><id>urn:md5:fe679e91e968a2d7cb6ae8ed5f6fad18</id><content type="html">&lt;p&gt;Si comme moi vous effectuez une veille quotidienne autour des outils et technologies Web, vous n&amp;#8217;avez certainement pas pu passer à côté de l&amp;#8217;engouement massif pour le langage &lt;a href="http://www.python.org/" hreflang="en"&gt;Python&lt;/a&gt; ces derniers temps. De plus en plus de développeurs PHP passent sur ce langage&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/10/12/Scrum.py%2C-pr%C3%A9sentation-et-conf%C3%A9rence-Scrum-et-Python-le-23-octobre-%C3%A0-Montpellier#pnote-1126-1" id="rev-pnote-1126-1"&gt;1&lt;/a&gt;]&lt;/sup&gt;, souvent par l&amp;#8217;entremise de l&amp;#8217;excellent framework &lt;a href="http://www.django-fr.org/" hreflang="fr"&gt;Django&lt;/a&gt;, que présentera mon camarade de jeu &lt;a href="http://www.biologeek.com/" hreflang="en"&gt;David Larlet&lt;/a&gt; le vendredi 23 octobre prochain à Montpellier à l&amp;#8217;occasion d&amp;#8217;une conférence donnée dans le cadre de l&amp;#8217;évènement &lt;a href="http://scrumpy.particul.es/" hreflang="fr"&gt;Scrum.py&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;L&amp;#8217;efficacité potentielle du meilleur outil technique étant réduit à néant s&amp;#8217;il n&amp;#8217;est pas efficacement encadré par une méthodologie de conduite de projet adapté aux contraintes d&amp;#8217;un métier souvent difficile, &lt;a href="http://www.aubryconseil.com/" hreflang="fr"&gt;Claude Aubry&lt;/a&gt;, un des tous meilleurs experts français sur le sujet, présentera quand à lui les avantages et intérêt de &lt;a href="http://fr.wikipedia.org/wiki/Scrum" hreflang="fr"&gt;Scrum&lt;/a&gt; durant cette même journée d&amp;#8217;information &lt;strong&gt;gratuite&lt;/strong&gt;, à laquelle je vous invite à &lt;a href="http://scrumpy.particul.es/scrum-python-django-montpellier/presentation" hreflang="fr"&gt;vous inscrire en ligne&lt;/a&gt; dès à présent.&lt;/p&gt;


&lt;p&gt;David proposera également un &lt;a href="http://scrumpy.particul.es/scrum-python-django-montpellier/formation-django" hreflang="fr"&gt;atelier Django les 18, 19 et 20 novembre prochains&lt;/a&gt;, tandis que Claude animera une &lt;a href="http://scrumpy.particul.es/scrum-python-django-montpellier/formation-scrum" hreflang="fr"&gt;formation Scrum les 2, 3 et 4 décembre&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;L&amp;#8217;évènement est organisé par le collectif &lt;a href="http://particul.es/" hreflang="fr"&gt;Particul.es&lt;/a&gt;, et les places, tant pour les conférences que pour les formations, sont limitées&amp;#160;; alors n&amp;#8217;hésitez pas à vous &lt;a href="http://scrumpy.particul.es/" hreflang="fr"&gt;inscrire rapidement&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src="http://scrumpy.particul.es/images/tag.png" alt="" style="display:block; margin:0 auto;" /&gt;&lt;/p&gt;
&lt;div class="footnotes"&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/10/12/Scrum.py%2C-pr%C3%A9sentation-et-conf%C3%A9rence-Scrum-et-Python-le-23-octobre-%C3%A0-Montpellier#rev-pnote-1126-1" id="pnote-1126-1"&gt;1&lt;/a&gt;] Et j&amp;#8217;avoue me réfréner fortement à faire de même tant les inconsistances de PHP me portent quotidiennement sur les nerfs&lt;/p&gt;&lt;/div&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/10/12/Scrum.py%2C-pr%C3%A9sentation-et-conf%C3%A9rence-Scrum-et-Python-le-23-octobre-%C3%A0-Montpellier"&gt;Scrum.py, présentation et conférence Scrum et Python le 23 octobre à Montpellier&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/zX1wsd7psTg" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/10/12/Scrum.py%2C-pr%C3%A9sentation-et-conf%C3%A9rence-Scrum-et-Python-le-23-octobre-%C3%A0-Montpellier</feedburner:origLink></entry><entry><title type="text">Simple Continuous Integration of a Symfony Project using Hudson</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/dyBeclmVXcY/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson" /><category term="Dev" /><category term="continuous integration" /><category term="hudson" /><category term="php" /><category term="symfony" /><category term="testing" /><author><name>NiKo</name></author><updated>2009-10-06T06:36:00-07:00</updated><id>urn:md5:48005890d8164cd0a43875105e74d9c0</id><content type="html">&lt;p&gt;I love tests, I just cannot program without them anymore, especially with &lt;a href="http://www.symfony-project.org/" hreflang="en"&gt;Symfony&lt;/a&gt;. And as I write a lot of them on a daily basis, the full test suite can take a very long time to be executed&amp;#160;; running a &lt;code&gt;symfony test:all&lt;/code&gt; command before every granular commit suppose you have to wait sometimes more than 5, 10 minutes or more for the whole tests to be ran: hardly acceptable. &lt;a href="http://svnbook.red-bean.com/en/1.4/svn.ref.reposhooks.post-commit.html" hreflang="en"&gt;Post commit hooks&lt;/a&gt; can be a solution, but what if a lot of devs are working simultaneously on the same project? Added to the previously seen test execution duration, it can become a problem difficult to deal with.&lt;/p&gt;


&lt;p&gt;Here comes &lt;a href="http://en.wikipedia.org/wiki/Continuous_integration" hreflang="en"&gt;continuous integration&lt;/a&gt;&amp;#160;: regularly, eg. every hour, the symfony project will be built up and configured from scratch, then the full test suite will be executed and the resulting log will be aggregated. It&amp;#8217;s a very convenient way to keep an eye on the overall code quality and integrity of the project.&lt;/p&gt;


&lt;p&gt;There are several open source continuous integration software available on the market: &lt;a href="http://cruisecontrol.sourceforge.net/" hreflang="en"&gt;Cruise Control&lt;/a&gt; (and &lt;a href="http://phpundercontrol.org/" hreflang="en"&gt;phpUnderControl&lt;/a&gt;), &lt;a href="http://continuum.apache.org/" hreflang="en"&gt;Continuum&lt;/a&gt;, &lt;a href="http://integrityapp.com/" hreflang="en"&gt;Integrity&lt;/a&gt;, the uncertain but awesomely looking &lt;a href="http://sismo-project.org/" hreflang="en"&gt;Sismo&lt;/a&gt; which powers the &lt;a href="http://ci.symfony-project.org/" hreflang="en"&gt;Symfony continous integration server&lt;/a&gt;&amp;#8230; But I recently had the opportunity to test &lt;a href="https://hudson.dev.java.net" hreflang="en"&gt;Hudson&lt;/a&gt;, a java based one. It&amp;#8217;s very simple to install, setup and configure, and has tons of plugins. So let&amp;#8217;s see how it can be used to test a Symfony project.&lt;/p&gt;


&lt;p&gt;&lt;a href="http://prendreuncafe.com/blog/public/images/Dev/Hudson/hudson_tests_weather.png"&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/Hudson/.hudson_tests_weather_m.jpg" alt="img hudson_tests_weather" style="display:block; margin:0 auto;" title="hudson_tests_weather.png, oct. 2009" /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;Hudson Installation&lt;/h3&gt;


&lt;p&gt;That&amp;#8217;s really not the hardest part, because you just need a working &lt;a href="http://java.sun.com/javase/downloads/index_jdk5.jsp" hreflang="en"&gt;JRE 1.5&lt;/a&gt; installation on your machine, and to &lt;a href="http://hudson-ci.org/latest/hudson.war" hreflang="en"&gt;retrieve the latest version of the program&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Then, you can launch it directly from a shell prompt:&lt;/p&gt;


&lt;pre&gt;$  java -jar /path/to/hudson.war&lt;/pre&gt;


&lt;p&gt;If you fear to break something or just want to give it a go without the hassle of firing a term, just launch the available &lt;a href="https://hudson.dev.java.net/hudson.jnlp" hreflang="en"&gt;Java Web Start version&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;On debian/ubuntu, it&amp;#8217;s just as easy as:&lt;/p&gt;


&lt;pre&gt;$ sudo echo deb http://hudson-ci.org/debian binary/ &amp;gt;&amp;gt; /etc/apt/sources.list
$ sudo apt-get update
$ sudo apt-get install hudson
$ sudo /etc/init.d/hudson start&lt;/pre&gt;


&lt;h3&gt;Configuration and Symfony Project Integration&lt;/h3&gt;


&lt;p&gt;Once Hudson is installed an running, head up to &lt;a href="http://localhost:8080/" hreflang="en"&gt;http://localhost:8080/&lt;/a&gt; and start playing with the web based user interface of Hudson. The navigation and configuration forms are quite obvious, and therefore efficient. Creating a project following the provided guidelines is easy and can be achieved within minutes:&lt;/p&gt;


&lt;p&gt;First, create a new Job, choosing the &lt;em&gt;Build a free-style software project&lt;/em&gt; option.&lt;/p&gt;


&lt;p&gt;Then, configure the subversion repository&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson#pnote-1125-1" id="rev-pnote-1125-1"&gt;1&lt;/a&gt;]&lt;/sup&gt; used by your project by entering its base URL in the &lt;em&gt;Source Code Management&lt;/em&gt; field
You can schedule builds, watch for SCM activity and even trigger builds from remote script using a neat XMLRPC interface&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson#pnote-1125-2" id="rev-pnote-1125-2"&gt;2&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;p&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/Hudson/hudson_svn.png" alt="img hudson_svn" style="display:block; margin:0 auto;" title="hudson_svn.png, oct. 2009" /&gt;&lt;/p&gt;


&lt;p&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/Hudson/hudson_scheduling.png" alt="img hudson_hudson_scheduling" style="display:block; margin:0 auto;" title="hudson_scheduling.png, oct. 2009" /&gt;&lt;/p&gt;


&lt;p&gt;Configuring the building process is as easy as writing down some commands, like the one you&amp;#8217;d execute to setup your project on a new box:&lt;/p&gt;


&lt;p&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/Hudson/hudson_build-commands.png" alt="img hudson_build_commands" style="display:block; margin:0 auto;" title="hudson_build-commands.png, oct. 2009" /&gt;&lt;/p&gt;


&lt;p&gt;As of Symfony 1.3, test result logs can be exported in a jUnit XML file, so Hudson will be able to parse them and provide some useful reports, metrics and charts:&lt;/p&gt;


&lt;p&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/Hudson/.huson_test_results_m.jpg" alt="huson_test_results.png" style="display:block; margin:0 auto;" title="huson_test_results.png, oct. 2009" /&gt;&lt;/p&gt;


&lt;p&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/Hudson/.hudson_tests_charts_m.jpg" alt="" style="display:block; margin:0 auto;" /&gt;&lt;/p&gt;


&lt;p&gt;Of course, you can configure failure notifications: email, atom feed, there&amp;#8217;s even a &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Twitter+Plugin" hreflang="en"&gt;twitter plugin&lt;/a&gt;!&lt;/p&gt;


&lt;p&gt;As a conclusion, Hudson is a very simple but efficient continous integration tool which can easily be configured to monitor the quality of your Symfony projects&amp;#8230; at least if you write tests &lt;img src="/blog/themes/battlestar/smilies/wink.gif" alt=";)" class="smiley" /&gt;&lt;/p&gt;
&lt;div class="footnotes"&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson#rev-pnote-1125-1" id="pnote-1125-1"&gt;1&lt;/a&gt;] If you&amp;#8217;re not using Subversion, lot of plugins are available for other SCM in the huge &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Plugins#Plugins-Sourcecodemanagement" hreflang="en"&gt;Hudson plugins repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson#rev-pnote-1125-2" id="pnote-1125-2"&gt;2&lt;/a&gt;] Useful if you wish to use post-commit build hook&lt;/p&gt;&lt;/div&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson"&gt;Simple Continuous Integration of a Symfony Project using Hudson&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/dyBeclmVXcY" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson</feedburner:origLink></entry><entry><title type="text">Optimize your Doctrine Workflow with Specialized Queries</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/Y2LtHS3ujUs/Optimize-your-Doctrine-Workflow-with-Specialized-Queries" /><category term="Dev" /><category term="bestpractices" /><category term="doctrine" /><category term="php" /><category term="query" /><category term="sql" /><category term="symfony" /><category term="tips" /><author><name>NiKo</name></author><updated>2009-09-15T10:14:00-07:00</updated><id>urn:md5:07be0ff35e1f2e047f2faca25323c26e</id><content type="html">&lt;p&gt;I&amp;#8217;m currently working on a big &lt;a href="http://www.symfony-project.org/" hreflang="en"&gt;Symfony&lt;/a&gt; project, with a lot of &lt;a href="http://www.doctrine-project.org/" hreflang="en"&gt;Doctrine&lt;/a&gt; models and complex queries to write. I found a way to organize all of them in an object-oriented and cleaner way than using the traditionnal &lt;code&gt;addNamedQuery()&lt;/code&gt; and &lt;code&gt;createNamedQuery()&lt;/code&gt; methods workflow&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#pnote-1123-1" id="rev-pnote-1123-1"&gt;1&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;p&gt;The idea is to create dedicated &lt;a href="http://www.doctrine-project.org/Doctrine_Query/1_2" hreflang="en"&gt;query&lt;/a&gt; classes for a given model&amp;#160;; this way, you can provide useful methods to build the business-related parts of your query.&lt;/p&gt;


&lt;p&gt;As usual, the theory is more understandable with a concrete example. Let&amp;#8217;s consider this simple Doctrine model&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#pnote-1123-2" id="rev-pnote-1123-2"&gt;2&lt;/a&gt;]&lt;/sup&gt;&amp;#160;:&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; The provided examples have been written in a hurry, so mistakes might have been not detected by my attentive proof-reading &lt;img src="/blog/themes/battlestar/smilies/wink.gif" alt=";)" class="smiley" /&gt;&lt;/p&gt;

&lt;pre&gt;BlogAuthor:
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true  
    name:
      type: string(255)
  relations:
    Post:
      type: one
      class: BlogPost
      local: id
      foreign: author_id
&amp;nbsp;
BlogPost:
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    author_id:
      type: integer(4)
      notnull: true
    title:
      type: string(255)
    content:
      type: string(65535)
  relations:
    Author:
      type: one
      class: BlogAuthor
      local: author_id
      foreign: id
    Comments:
      type: many
      class: BlogComment
      local: id
      foreign: post_id
&amp;nbsp;
BlogComment:
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    post_id:
      type: integer(4)
      notnull: true
    author:
      type: string(255)
    content:
      type: string(5000)
  relations:
    Post:
      type: one
      class: BlogPost
      local: post_id
      foreign: id&lt;/pre&gt;


&lt;p&gt;Now let&amp;#8217;s imagine a Query class dedicated to query the BlogPost table:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt; BlogPostQuery extends Doctrine_Query
&lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/static"&gt;&lt;span style="color: #000066;"&gt;static&lt;/span&gt;&lt;/a&gt; public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; create&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$conn&lt;/span&gt; = &lt;span style="color: #000000; font-weight: bold;"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;$class&lt;/span&gt; = &lt;span style="color: #000000; font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; parent::&lt;span style="color: #006600;"&gt;create&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$conn&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'BlogPostQuery'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;from&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'BlogPost p'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
  
  public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; addPosts&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$fields&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;'p.*'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span style="color: #006600;"&gt;addSelect&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'p.*'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
  
  public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; addComments&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$fields&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;'c.*'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;$this&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addSelect&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$fields&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;leftJoin&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'p.Comments c'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addGroupBy&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'c.id'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
  
  public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; addAuthors&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$fields&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;'a.*'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;$this&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addSelect&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$fields&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;leftJoin&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'p.Author a'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addGroupBy&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'a.id'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
  
  public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; addCommentsCount&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$alias&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;'nb_comments'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;$this&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addSelect&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/sprintf"&gt;&lt;span style="color: #000066;"&gt;sprintf&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'COUNT(c.id) as %s'&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;$alias&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addGroupBy&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'c.id'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
  
  public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; filterByAuthorName&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$authorName&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;$this&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;andWhere&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'a.name = ?'&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;$authorName&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;So how can we use this query object? Here are some sample uses:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span style="color: #808080; font-style: italic;"&gt;// Retrieve all posts&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;$posts&lt;/span&gt; = BlogPostQuery::&lt;span style="color: #006600;"&gt;create&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addPosts&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;fetchArray&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span style="color: #808080; font-style: italic;"&gt;// Retrieve all posts with comments&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;$posts&lt;/span&gt; = BlogPostQuery::&lt;span style="color: #006600;"&gt;create&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addPosts&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addComments&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;fetchArray&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span style="color: #808080; font-style: italic;"&gt;// Retrieve all posts with comments and their count per post&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;$posts&lt;/span&gt; = BlogPostQuery::&lt;span style="color: #006600;"&gt;create&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addPosts&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addComments&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addCommentsCount&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'yataa'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;fetchArray&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span style="color: #808080; font-style: italic;"&gt;// Retrieve all post with chuck as its author and related comments&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;$posts&lt;/span&gt; = BlogPostQuery::&lt;span style="color: #006600;"&gt;create&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addAuthors&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addPosts&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;addComments&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;filterByAuthorName&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'chuck'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  -&amp;gt;&lt;span style="color: #006600;"&gt;fetchArray&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span style="color: #808080; font-style: italic;"&gt;// and so on... &lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;Of course, this example of use is not really relevant as our model is really simple, but when you&amp;#8217;re dealing with dozens of internationalized objects, it can help cleaning your model classes, controllers and improving the organization of your work.&lt;/p&gt;


&lt;h3&gt;Update and important precisions&lt;/h3&gt;


&lt;p&gt;Some people are having negative feedback regarding this technique, claiming it will encourage people using the custom query object directly in the controllers; that&amp;#8217;s absolutely not the case as the queries are to be used only within the model layer, for example in the &lt;code&gt;BlogPostTable&lt;/code&gt; class:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt; BlogPostTable extends Doctrine_Table
&lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/static"&gt;&lt;span style="color: #000066;"&gt;static&lt;/span&gt;&lt;/a&gt; public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; getPostsWithCommentsByAuthor&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$authorName&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; BlogPostQuery::&lt;span style="color: #006600;"&gt;create&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addPosts&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;addComments&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;filterByAuthorName&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$authorName&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
      -&amp;gt;&lt;span style="color: #006600;"&gt;fetchArray&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
    ;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;And in a controller:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt; blogActions extends sfActions
&lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
  public &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; executeListByAuthor&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;sfWebRequest &lt;span style="color: #0000ff;"&gt;$request&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;
  &lt;span style="color: #66cc66;"&gt;&amp;#123;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span style="color: #006600;"&gt;posts&lt;/span&gt; = BlogPostTable::&lt;span style="color: #006600;"&gt;getPostsWithCommentsByAuthor&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$request&lt;/span&gt;-&amp;gt;&lt;span style="color: #006600;"&gt;getParameter&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'author'&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;
&lt;span style="color: #66cc66;"&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;div class="footnotes"&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#rev-pnote-1123-1" id="pnote-1123-1"&gt;1&lt;/a&gt;] &amp;#8230; or raw queries written directly within controllers, but you may know that &lt;a href="http://www.slideshare.net/nperriault/30-symfony-best-practices" hreflang="en"&gt;this is really bad&lt;/a&gt; &lt;img src="/blog/themes/battlestar/smilies/wink.gif" alt=";)" class="smiley" /&gt;&lt;/p&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#rev-pnote-1123-2" id="pnote-1123-2"&gt;2&lt;/a&gt;] I&amp;#8217;m using Doctrine 1.2 beta (bundled with upcoming symfony 1.3) in the provided example.&lt;/p&gt;&lt;/div&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries"&gt;Optimize your Doctrine Workflow with Specialized Queries&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/Y2LtHS3ujUs" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries</feedburner:origLink></entry><entry><title type="text">30 Symfony Best Practices, the slides from my talk at SymfonyDay Cologne '09</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/2h9rKZz9OaE/30-Symfony-Best-Practices%2C-the-slides-from-my-talk-at-SymfonyDay-Cologne-09" /><category term="Dev" /><category term="bestpractices" /><category term="php" /><category term="sfdaycgn" /><category term="symfony" /><author><name>NiKo</name></author><updated>2009-09-04T11:50:00-07:00</updated><id>urn:md5:b3db81a6e20a143a4e03c71d6b81c16f</id><content type="html">&lt;p&gt;Hey there, it&amp;#8217;s been a while, huh?&lt;/p&gt;


&lt;p&gt;Today I gave a talk about Symfony best practices at the &lt;a href="http://www.symfonyday.com/" hreflang="en"&gt;Symfony Day event in Cologne, Germany&lt;/a&gt;; you can &lt;a href="http://www.slideshare.net/nperriault/30-symfony-best-practices" hreflang="en"&gt;get the slides on slideshare&lt;/a&gt; or directly browse them below:&lt;/p&gt;

&lt;object type="application/x-shockwave-flash" data="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=30symfonybestpractices-090904074841-phpapp01&amp;amp;stripped_title=30-symfony-best-practices" width="425" height="344" style="width:425px;height:344px;margin:0 auto"&gt;
  &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=30symfonybestpractices-090904074841-phpapp01&amp;amp;stripped_title=30-symfony-best-practices" /&gt;
  &lt;param name="wmode" value="transparent" /&gt;
  &lt;param name="allowFullScreen" value="true" /&gt;
  &lt;param name="allowScriptAccess" value="always" /&gt;
  
&lt;/object&gt;



&lt;p&gt;The Symfony Day event has been purely awesomely incredibly well organized, many kudos and thanks to &lt;a href="http://www.interlutions.de/" hreflang="de"&gt;Interlutions&lt;/a&gt; and to all the attendees. You&amp;#8217;re all great people. Thanks.&lt;/p&gt;

&lt;a href="http://www.flickr.com/photos/n1k0/3886662176/" title="Symfony Day '09 Cologne by Nicolas Perriault, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2555/3886662176_8f0826e610.jpg" width="500" height="333" alt="Symfony Day '09 Cologne" /&gt;&lt;/a&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/09/04/30-Symfony-Best-Practices%2C-the-slides-from-my-talk-at-SymfonyDay-Cologne-09"&gt;30 Symfony Best Practices, the slides from my talk at SymfonyDay Cologne '09&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/2h9rKZz9OaE" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/09/04/30-Symfony-Best-Practices%2C-the-slides-from-my-talk-at-SymfonyDay-Cologne-09</feedburner:origLink></entry><entry><title type="text">YAML Brush for the SyntaxHighlighter Javascript Library</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/15nVaiQG5jc/YAML-Brush-for-the-SyntaxHighlighter-Javascript-Library" /><category term="Dev" /><category term="code" /><category term="javascript" /><category term="syntax highlighting" /><category term="syntaxhighlighter" /><author><name>NiKo</name></author><updated>2009-07-26T04:48:00-07:00</updated><id>urn:md5:8ec97f12c6dc738c90136befa2a3552f</id><content type="html">&lt;p&gt;During a trip back to Paris by train, I quickly coded for a project of mine a new brush for &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter" hreflang="en"&gt;SyntaxHighlighter&lt;/a&gt;, a client-side syntax coloring library powered by Javascript, in order to highlight &lt;a href="http://yaml.org/" hreflang="en"&gt;YAML&lt;/a&gt; code snippets.&lt;/p&gt;


&lt;p&gt;&lt;img src="http://prendreuncafe.com/blog/public/images/Dev/JavaScript/shYaml.png" alt="YAML syntax highlighting brush" style="display:block; margin:0 auto;" title="YAML syntax highlighting brush, juil. 2009" /&gt;&lt;/p&gt;


&lt;p&gt;You can &lt;a href="http://alexgorbatchev.com/forums/?PostBackAction=Download&amp;amp;AttachmentID=22" hreflang="en"&gt;get the code here&lt;/a&gt; and provide feedback in &lt;a href="http://alexgorbatchev.com/forums/comments.php?DiscussionID=128&amp;amp;page=1" hreflang="en"&gt;a dedicated thread on the official forum&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; Oops, didn&amp;#8217;t find this already &lt;a href="http://www.willdurand.fr/posts/10/syntaxhighlighter-tinymce-et-yml.html" hreflang="en"&gt;existing brush&lt;/a&gt; (I hadn&amp;#8217;t wifi access in the train). I think my version support more specific aspects of the syntax, though.&lt;/p&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/07/26/YAML-Brush-for-the-SyntaxHighlighter-Javascript-Library"&gt;YAML Brush for the SyntaxHighlighter Javascript Library&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/15nVaiQG5jc" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/07/26/YAML-Brush-for-the-SyntaxHighlighter-Javascript-Library</feedburner:origLink></entry><entry><title type="text">Installing php 5.3, apache2 and MySQL 5 on OS X using Macports</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/prendreuncafe/~3/DFkKs9YP0AM/Installing-php-5.3%2C-apache2-and-MySQL-5-using-Macports" /><category term="Libritudes" /><category term="apache" /><category term="apple" /><category term="howto" /><category term="mac" /><category term="macports" /><category term="mysql" /><category term="osx" /><category term="php" /><category term="server" /><category term="setup" /><category term="tutoriel" /><author><name>NiKo</name></author><updated>2009-07-17T05:40:00-07:00</updated><id>urn:md5:19c5389e0b0ecafc469ac42b8c521dc0</id><content type="html">&lt;p&gt;I wanted to test latest php 5.3 on my OSX box. So here&amp;#8217;s a quick reminder on how to proceed to a full setup of apache2, mysql5 and php 5.3 using &lt;a href="http://www.macports.org/install.php" hreflang="en"&gt;Macports&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;First, get a &lt;a href="http://www.macports.org/install.php" hreflang="en"&gt;fresh copy of the Macports installer for OSX&lt;/a&gt;. Install macports, then in a shell prompt, type:&lt;/p&gt;

&lt;pre&gt;
$ sudo port install mysql5 +server
$ sudo port install php5 +apache2 +debug +pear +sqlite +mysql5 
&lt;/pre&gt;


&lt;p&gt;You have now the time to have lunch, dinner, sex or to watch an episode of &lt;a href="http://www.imdb.com/title/tt0070981/" hreflang="en"&gt;Derrick&lt;/a&gt;&lt;sup&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/07/17/Installing-php-5.3%2C-apache2-and-MySQL-5-using-Macports#pnote-1120-1" id="rev-pnote-1120-1"&gt;1&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;p&gt;To enable the php module for apache:&lt;/p&gt;

&lt;pre&gt;
$ cd /opt/local/apache2/modules
$ sudo /opt/local/apache2/bin/apxs -a -e -n &amp;quot;php5&amp;quot; libphp5.so
&lt;/pre&gt;


&lt;p&gt;Then, add this line in the &lt;code&gt;/opt/local/apache2/conf/httpd.conf&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;
Include conf/extras-conf/*.conf
&lt;/pre&gt;


&lt;p&gt;Copy one of the standard &lt;code&gt;php.ini&lt;/code&gt; files proposed by the default installation:&lt;/p&gt;

&lt;pre&gt;
$ sudo cp /opt/local/etc/php5/php.ini-development /opt/local/etc/php5/php.ini
&lt;/pre&gt;


&lt;p&gt;To start apache automatically at system startup:&lt;/p&gt;

&lt;pre&gt;
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plist
&lt;/pre&gt;


&lt;p&gt;Or manually:&lt;/p&gt;

&lt;pre&gt;
$ sudo /opt/local/apache2/bin/apachectl start
&lt;/pre&gt;


&lt;p&gt;To initialize, configure and start MySQL automatically:&lt;/p&gt;

&lt;pre&gt;
$ sudo -u mysql mysql_install_db5
$ sudo /opt/local/bin/mysql_secure_installation5
$ sudo /opt/local/etc/LaunchDaemons/org.macports.mysql5/mysql5.wrapper start
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist
&lt;/pre&gt;


&lt;p&gt;Now launch your browser at &lt;code&gt;http://localhost/&lt;/code&gt;: you&amp;#8217;re done. Have some rest.&lt;/p&gt;
&lt;div class="footnotes"&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href="http://prendreuncafe.com/blog/post/2009/07/17/Installing-php-5.3%2C-apache2-and-MySQL-5-using-Macports#rev-pnote-1120-1" id="pnote-1120-1"&gt;1&lt;/a&gt;] Don&amp;#8217;t try to do all that stuff at the same time, result cannot be guaranteed&lt;/p&gt;&lt;/div&gt;&lt;hr/&gt;&lt;p style="margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222"&gt;&lt;small&gt;Ce billet intitulé &lt;a href="http://prendreuncafe.com/blog/post/2009/07/17/Installing-php-5.3%2C-apache2-and-MySQL-5-using-Macports"&gt;Installing php 5.3, apache2 and MySQL 5 on OS X using Macports&lt;/a&gt; a été rédigé par &lt;a href="http://prendreuncafe.com/cv"&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href="http://prendreuncafe.com/blog/"&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/prendreuncafe/~4/DFkKs9YP0AM" height="1" width="1"/&gt;</content><feedburner:origLink>http://prendreuncafe.com/blog/post/2009/07/17/Installing-php-5.3%2C-apache2-and-MySQL-5-using-Macports</feedburner:origLink></entry></feed>
