<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Romain Dorgueil</title>
 <link href="http://romain.dorgueil.net/atom.xml" rel="self"/>
 <link href="http://romain.dorgueil.net/blog/"/>
 <updated>2011-09-05T13:24:00+02:00</updated>
 <id>http://romain.dorgueil.net/blg/</id>
 <author>
   <name>Romain Dorgueil</name>
   <email>romain@dorgueil.net</email>
 </author>

 
 <entry>
   <title><span class="headline">php</span> I see huge controllers ...</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/php/2011/09/05/i-see-huge-controllers.html"/>
   <updated>2011-09-05T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/php/2011/09/05/i-see-huge-controllers</id>
   <content type="html">&lt;p&gt;As I'm lazy today, I will delay the python+wsgi tutorial a bit and finish an
article I started months ago. I never took the time to publish it, but as I am
re-reading it, I think it deserves it.&lt;/p&gt;

&lt;div style=&quot;float: left; margin-right: 2em&quot; &gt;
    &lt;figure style=&quot;margin-top:2em; margin-bottom: 2em;&quot; align=&quot;center&quot;&gt; 
        &lt;img width=&quot;250&quot; height=&quot;405&quot;  src=&quot;/blog/images/spaghettis.jpg&quot;
            title=&quot;Well ordered cables&quot; alt=&quot;A nice way to sort your cables&quot; /&gt;
        &lt;figcaption style=&quot;width: 250px&quot;&gt;
            A commonly seen web application architecture.
        &lt;/figcaption&gt;
    &lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;So at that time, I was working for a client which needed some help to make one
project live.  The project was 90% done, and it was written using symfony
(1.4).&lt;/p&gt;

&lt;p&gt;It was pretty small-sized: about 10 symfony modules (maybe fewer) and a
two part model layer having a doctrine-mapped tiny database, and a kind of
facade to Facebook APIs.&lt;/p&gt;

&lt;p&gt;But surprisingly enough, a project this small contained a &lt;em&gt;lot&lt;/em&gt; of complexity,
duplicates, misplacement ...&lt;/p&gt;

&lt;p&gt;The project was about functionnal, just needed a &quot;final polish&quot; from a user
perspective, and some little missing features, but not huge of a deal.&lt;/p&gt;

&lt;p&gt;On the other hand, the application was a hell to read, understand, and maintain
already. Even before it went live.&lt;/p&gt;

&lt;p&gt;The direct consequence of this is to make each subsequent development longer,
and thus more expensive. The less-seen consequence is also to exhaust
developpers because it make them feel unproductive. And you don't want your
team to be exhausted. Never.&lt;/p&gt;

&lt;p&gt;So please, please, please, think about the project lifetime when you're doing
development. And even more important, show respect to your present and future
coworkers, and thus to yourself ...&lt;/p&gt;

&lt;div class=&quot;floatfix&quot;&gt;&lt;/div&gt;


&lt;h2&gt;Huge controllers&lt;/h2&gt;

&lt;p&gt;It should be pretty obvious to anybody, but I'm pretty sure all you have
experienced this.&lt;/p&gt;

&lt;p&gt;People tend to see controller methods as bins they can put any code in. They
will just think &quot;Hey, I'm pragmatic, and this works. Yay, kudos from my
manager.&quot;.&lt;/p&gt;

&lt;p&gt;That's for sure a pragmatic way to get kudos at first.&lt;/p&gt;

&lt;p&gt;The fact is that the &quot;you're wrong&quot; part is completely invisible to your
manager. And one day he wants to go live with his project.&lt;/p&gt;

&lt;p&gt;The problems are coming now.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Manager: &quot;Hey the app is slow, speed it up.&quot;&lt;/p&gt;

&lt;p&gt;Dev: &quot;Well I guess the model calls are getting long, it's doctrine fault.&quot;&lt;/p&gt;

&lt;p&gt;M.: &quot;Ok fix it.&quot;&lt;/p&gt;

&lt;p&gt;D.: &quot;Well, I'll have to go through all the controllers, change all calls ...
It'll take one week at least.&quot;&lt;/p&gt;

&lt;p&gt;M.: &quot;Change controllers to fix the model? Huhu... I guess I missed something
but hey, you're the pro, go ahead.&quot;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Then the developper takes two week to vaguely fix some calls, cache some really
long request ... What I'd call &quot;hide problems under the carpet&quot;.&lt;/p&gt;

&lt;p&gt;But when you go live again, you just notice that only half the model problems
are fixed. Woops, it happened that this famous model code in controllers was in
fact present in quite a bunch of controllers, and the developper missed some.&lt;/p&gt;

&lt;p&gt;And now we're starting to spot the exact same problem with some SOAP calls ...&lt;/p&gt;

&lt;p&gt;Of course at the very last, you will end up fixing the app, at least enough for
it to survive the ridiculous amount of target traffic, but the overall problem
is not there ...&lt;/p&gt;

&lt;p&gt;So let me recall some base principles.&lt;/p&gt;

&lt;h2&gt;One place for each stuff, and each stuff at the right place&lt;/h2&gt;

&lt;p&gt;Sounds idiomatic, but...&lt;/p&gt;

&lt;p&gt;Model logic goes into the model.&lt;/p&gt;

&lt;p&gt;The &quot;model&quot; layer is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Facade_pattern&quot;&gt;facade&lt;/a&gt;
that provides you with a business data access and manipulation API.&lt;/p&gt;

&lt;p&gt;Write the API once, and then use it. Said simplier, &lt;em&gt;you're not allowed to
access data by anyelse mean&lt;/em&gt;. May it be database, SOAP/REST calls, or some
other remote service providing some data to you (like Facebook) ...&lt;/p&gt;

&lt;p&gt;Let me say it again, it's &lt;em&gt;FORBIDDEN&lt;/em&gt;. Thinking of this
&amp;laquo;&lt;em&gt;shortcut&lt;/em&gt;&amp;raquo; as a way to speed development up is just stupid.&lt;/p&gt;

&lt;h3&gt;Organize your model layer&lt;/h3&gt;

&lt;p&gt;One big misconception a lot of people have is to think as their favorite ORM as
the model layer of their project. Yes the ORM is a part of the model layer, but
it's not necessary the whole model layer. You're allowed and encouraged to add
proxies and facades in it, providing a nice, clean, and documented public API.&lt;/p&gt;

&lt;p&gt;In an ideal world, the whole &quot;data access&quot; mechanism should be hidden and only
a documented chosen subset of the model API should be used in your controllers.&lt;/p&gt;

&lt;h3&gt;Group features by concerns&lt;/h3&gt;

&lt;p&gt;You have plenty of tools to do this that are pretty much language/framework
specific. In symfony (1), you have applications, modules, plugins ...&lt;/p&gt;

&lt;p&gt;Take 5 minutes to think of the right place to do something, you'll save 10
minutes a day forever. Repeat.&lt;/p&gt;

&lt;h2&gt;Don't repeat yourself&lt;/h2&gt;

&lt;p&gt;What? This one again?&lt;/p&gt;

&lt;p&gt;Yes, but I'll reword.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You're &lt;strong&gt;not allowed&lt;/strong&gt; to have the same code, or same logic twice&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let me give you some methodology for this. First of all, you must be familiar
with your project, and know the codebase. You will obvsiously write duplicate
logic if you are not.&lt;/p&gt;

&lt;p&gt;If you're not familiar with the codebase, talk a lot, communicate, ask stupid
questions to people around, ask again, grep the code ... In short, find a way
to fill your knowledge gap.&lt;/p&gt;

&lt;p&gt;If you're familiar with the codebase, then you know that the logic you're
writing is already somewhere else. Unless the &quot;elsewhere&quot; code is useable to
solve your problem without changing anything, go ahead and write the logic fast
and dirty wherever you want, until you get it working.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now is the time to refactor&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&quot;There are two different times to do something. Now, and later. Later will
in fact be never, 95% of the time.&quot;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So do it &lt;em&gt;NOW&lt;/em&gt;, or it'll never be done.&lt;/p&gt;

&lt;p&gt;Take the two code snippets, think of what ideal place this shoud go, what ideal
API you want to use to do it ... And refactor &lt;em&gt;now&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By the way it's a great time to add up some doc. Just a bit, just enough. What
is this method, what is the input, what is the output. It should not take more
than one minute, and this is API part, so you need to understand how it works
at a glance.&lt;/p&gt;

&lt;p&gt;The whole thing took maybe 10 minutes more than if you left duplicate code, and
saved a lot of maintenance time ... An infinite maintenance time.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;There should be one-- and preferably only one --obvious way to do it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Zen of Python, by Tim Peters&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;So ?&lt;/h2&gt;

&lt;p&gt;This article was written looking at a symfony project, but I'm pretty certain
it can apply to all PHP projects, and by extend to all web projects designed
under an MVC-like architecture.&lt;/p&gt;

&lt;p&gt;May it be Python, Java, Ruby or anything ... The general idea is not language
specific, even if you may have language specific ways to do the underlying
stuff.&lt;/p&gt;

&lt;p&gt;If you allow yourself to bypass the &quot;let's do it clean&quot; part, then you're not
building web software, you're overcooking spaghettis (and you even forgot the
salt).&lt;/p&gt;

&lt;p&gt;&amp;laquo;Beurk&amp;raquo;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title><span class="headline">python</span> Give your WSGI application super-powers</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/python/2011/08/29/give-your-app-superpowers.html"/>
   <updated>2011-08-29T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/python/2011/08/29/give-your-app-superpowers</id>
   <content type="html">&lt;p&gt;&lt;img width=&quot;220&quot; height=&quot;246&quot; src=&quot;/blog/images/hulk_simpson.png&quot; title=&quot;Hulk Simpson&quot; alt=&quot;Hulk Simpson&quot; style=&quot;float: left; margin-right: 2em;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I agree that our last week &quot;Hello World&quot; application was not very impressive.&lt;/p&gt;

&lt;p&gt;In fact I don't think any &quot;Hello World&quot; can be impressive at all, unless it has
some mighty not-hello-world-at-all features.&lt;/p&gt;

&lt;p&gt;Let's sum up what we have so far. We have a &lt;em&gt;python script&lt;/em&gt;, that &lt;em&gt;spawns a
webserver&lt;/em&gt; on port 2222 and &lt;em&gt;answers HTTP requests&lt;/em&gt; saying hello.&lt;/p&gt;

&lt;p&gt;For a ten line script, it's not so bad, but still hello-word-ish.&lt;/p&gt;

&lt;p&gt;Baah.&lt;/p&gt;

&lt;div class=&quot;floatfix&quot;&gt;&lt;/div&gt;


&lt;h2&gt;About middlewares&lt;/h2&gt;

&lt;div style=&quot;float: right; margin-left: 2em; width: 300px&quot; align=&quot;center&quot;&gt;
    &lt;figure style=&quot;margin-top:0&quot;&gt; 
        &lt;a href=&quot;/blog/images/wsgi_middleware.png&quot; rel=&quot;wsgi-overview&quot;&gt;
            &lt;img src=&quot;/blog/images/wsgi_middleware_tn.png&quot; /&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;This diagram is part of &lt;a target=&quot;_blank&quot;
        href=&quot;https://docs.pylonsproject.org/projects/pylons_framework/dev/concepts.html#wsgi-middleware&quot;&gt;the
        Pylons Project documentation&lt;/a&gt;&lt;/figcaption&gt; 
    &lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;WSGI introduce the concept of &quot;middlewares&quot; (&lt;em&gt;Les wares du milieu&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;It is, like WSGI, a very simple concept. As all your WSGI applications have the
same prototype, it's very easy to create decorators that would be reusable WSGI
application enhancers.&lt;/p&gt;

&lt;p&gt;The picture on right, which comes from the Pylons framework documentation,
explain it graphically. Of course the layers presented here are only an example
from the said framework, and your setup is only limited by your immagination.&lt;/p&gt;

&lt;div class=&quot;floatfix&quot;&gt;&lt;/div&gt;




&lt;div class=&quot;info&quot;&gt;
    This is not unique to python, nor revolutionnary. The &quot;middleware&quot; concept
    is pretty similar to ruby's rack or to symfony's filter chain.
&lt;/div&gt;


&lt;h2&gt;The most amazing middleware ever: ajax interactive debugger&lt;/h2&gt;

&lt;p&gt;Let me introduce a new friend, &lt;strong&gt;weberror&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At a first glance, weberror interface may look like any other stack trace
dumper from &lt;em&gt;&amp;lt;insert-your-favorite-language-or-framework-here&amp;gt;&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;album floatfix&quot;&gt;
    &lt;a href=&quot;/blog/images/weberror/overview1.gif&quot; rel=&quot;weberror-overview&quot;&gt;
        &lt;figure&gt; 
            &lt;img src=&quot;/blog/images/weberror/overview1_tn.gif&quot; /&gt;
            &lt;figcaption&gt;Read stack trace ...&lt;/figcaption&gt; 
        &lt;/figure&gt;
    &lt;/a&gt;
    &lt;a href=&quot;/blog/images/weberror/overview2.gif&quot; rel=&quot;weberror-overview&quot;&gt;
        &lt;figure&gt; 
            &lt;img src=&quot;/blog/images/weberror/overview2_tn.gif&quot; /&gt;
            &lt;figcaption&gt;Look at environment ...&lt;/figcaption&gt; 
        &lt;/figure&gt;
    &lt;/a&gt;
    &lt;a href=&quot;/blog/images/weberror/overview3.gif&quot; rel=&quot;weberror-overview&quot;&gt;
        &lt;figure&gt; 
            &lt;img src=&quot;/blog/images/weberror/overview3_tn.gif&quot; /&gt;
            &lt;figcaption&gt;Show me the source ...&lt;/figcaption&gt; 
        &lt;/figure&gt;
    &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;But if you take a few seconds to explore it, you will get why it's 100 times
more powerfull. The huge difference is that you can expand a frame (using the
little plus icon) to get an interactive python interpreter in the context of
the stack frame.&lt;/p&gt;

&lt;div&gt;
    &lt;figure&gt;
        &lt;img src=&quot;/blog/images/weberror/interpreter1.gif&quot; /&gt;
        &lt;figcaption&gt;Type some python ...&lt;/figcaption&gt; 
    &lt;/figure&gt;

    &lt;figure&gt;
        &lt;img src=&quot;/blog/images/weberror/interpreter2.gif&quot; /&gt;
        &lt;figcaption&gt;Feel like you're within your application.&lt;/figcaption&gt; 
    &lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;This is great, but looks like a hell to integrate in some home-made
application... Actually it is not! Weberror contains a WSGI middleware that
will enpower any WSGI compliant application with its features. Let's add it to
our last week's application.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob.dec&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgify&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;weberror.evalexception&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EvalException&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AjaxDebuggerMiddleware&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@wsgify&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;/error&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Guess what, an error happened!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hello, debuggable world at &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AjaxDebuggerMiddleware&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WSGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve_forever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note that the feature costs 2 line of python (one import, and the decoration of
our original app). We added 2 more lines to raise an error if the URL is /error.&lt;/p&gt;

&lt;div class=&quot;warning&quot;&gt;
    Please note that doing this opens a huge backdoor in your application, as
    any uncaught exception will give the http client a python shell on your
    box. Be responsible with what you're doing, or you'll have problems. Huge
    ones.
&lt;/div&gt;


&lt;p&gt;To avoid the usual mistake of running the app bundled with the debugger unless
we really want to, let's add a &lt;strong&gt;--debug&lt;/strong&gt; command line option that enables it.&lt;/p&gt;

&lt;div class=&quot;info&quot;&gt;
    We are using &lt;strong&gt;optparse&lt;/strong&gt; module which is deprecated as of
    Python 2.7. You should consider using the &lt;strong&gt;argparse&lt;/strong&gt; module
    if you're using a recent Python version.
&lt;/div&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob.dec&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgify&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@wsgify&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;/error&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Guess what, an error happened!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hello, debuggable world at &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;optparse&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OptionParser&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OptionParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;-D&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;--debug&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;debug&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;store_true&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;activate the interactive web debugger&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;weberror.evalexception&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EvalException&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AjaxDebuggerMiddleware&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AjaxDebuggerMiddleware&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WSGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve_forever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You can now try the new features.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python middleware2.py --help
Usage: middleware2.py &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;options&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

Options:
  -h, --help   show this &lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;message and &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
  -D, --debug  activate the interactive web debugger
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Ok, and now what ?&lt;/h2&gt;

&lt;p&gt;Now you've seen one of the most stunning middleware that exists, let's think of
other cool usage our framework may need. Note that I'm not claiming all of
those features are actually good ideas to be implemented as middleware, but
they are implementable this way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Middlewares can intercept requests ...

&lt;ul&gt;
&lt;li&gt;One can route requests between several WSGI applications (subdomains ?)&lt;/li&gt;
&lt;li&gt;One can handle HTTP cache using HTTP headers. If a cached version is there,
the request won't go to the next WSGI layer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Middlewares can intercept outgoing stuff ...

&lt;ul&gt;
&lt;li&gt;One can consider logging unhandled errors on a prod server, or even sending
mails about them.&lt;/li&gt;
&lt;li&gt;One can look at the request &lt;em&gt;Accept&lt;/em&gt; header and provide content type
adapters for unacceptable types. You don't know about XML ? Let me present
you an HTML view of this file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Middlewares can put additionnal informations in the WSGI environment dict.

&lt;ul&gt;
&lt;li&gt;One can handle session storage/loading.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;And much more ...&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The drawback of using middlewares is that it adds complexity to your
application factory (the callable responsible for building the wsgi app).&lt;/p&gt;

&lt;p&gt;As soon as you want to switch components painlessly, middlewares are starting
to get in your way. You probably won't ever change the debugger, only enable or
disable it, so the middleware solution is fine.&lt;/p&gt;

&lt;p&gt;But what about session handling for example ? Or cache backends ? It's
completely possible to use middlewares, and you may have a look at
&lt;a href=&quot;https://beaker.groovie.org/&quot;&gt;&lt;strong&gt;beaker&lt;/strong&gt;&lt;/a&gt; that contains middlewares for caching
and sessions.&lt;/p&gt;

&lt;p&gt;However, we'll add those features using a much more flexible technique very
soon.&lt;/p&gt;

&lt;script&gt;
    $(document).ready(function(){
        $(&quot;a[rel='weberror-overview']&quot;).colorbox();
        $(&quot;a[rel='wsgi-overview']&quot;).colorbox();
    });
&lt;/script&gt;



</content>
 </entry>
 
 <entry>
   <title><span class="headline">python</span> WSGI, the first steps</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/python/2011/08/22/wsgi-the-first-steps.html"/>
   <updated>2011-08-22T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/python/2011/08/22/wsgi-the-first-steps</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/blog/images/python.png&quot; title=&quot;Python&quot; alt=&quot;Python&quot; style=&quot;float: left; margin-right: 1em&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Building web apps in python is quite a lot of fun, and so I decided to write a
little micro-framework from scratch. Today we will only think about interface
with the webserver, using WSGI.&lt;/p&gt;

&lt;p&gt;WSGI is the de-facto standard to interface a web application with a server
(also known as &quot;gateway&quot;). You may read the PEP 3333 to learn more about it,
but here I want to go straight to building a little wsgi app.&lt;/p&gt;

&lt;p&gt;WSGI applications have an onion architecture. The application is in the middle,
the webserver is outside, and a certain number of middlewares inbetween can
gives your application extra super-powers.&lt;/p&gt;

&lt;h2&gt;Get your environment ready&lt;/h2&gt;

&lt;p&gt;To build our application, we'll use a virtual environment to isolate our
experiments.&lt;/p&gt;

&lt;p&gt;Let's install some packages. Depending on your system, python-pip may be not
available and python-setuptools will replace it well (you'll need to use
&lt;code&gt;easy_install&lt;/code&gt; instead of &lt;code&gt;pip&lt;/code&gt; to install python packages, but this is outside
the scope of this blog post).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sh&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sudo apt-get install python-virtualenv python python-pip build-essential libevent-dev python-dev
    &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkdir wsgi-test
    &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;wsgi-test
    &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;virtualenv --no-site-packages wsgi-test.env
    &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;. wsgi-test.env/bin/activate
    &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip install webob weberror gevent
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This article has been written using python 2.6, but should be ok for
python&gt;=2.5. It probably needs some adjustements for python&gt;=3.0&lt;/p&gt;

&lt;h2&gt;First application&lt;/h2&gt;

&lt;p&gt;A WSGI application is basically a python callable which takes some parameters
and returns an iterator on the response body parts. The input parameters are an
&lt;code&gt;environment&lt;/code&gt; dict, and a &lt;code&gt;start_response&lt;/code&gt; callable which you'll call to start
sending the headers.&lt;/p&gt;

&lt;p&gt;Let's write the first app.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wsgi_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;200 OK&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hello, little world.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WSGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve_forever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This app is a bit minimalist, but it works. You can run the file and check
http://localhost:2222/.&lt;/p&gt;

&lt;div class=&quot;info&quot;&gt;
  We're using &lt;em&gt;gevent&lt;/em&gt; to embed a webserver in our application because
  it's fast and easy. Almost every webserver have WSGI support, either builtin
  or using extensions, so you can switch to whatever you like. Using
  &lt;em&gt;Apache&lt;/em&gt; for example, you can run your application using
  &lt;em&gt;mod_wsgi&lt;/em&gt;. Configuring a web server is out of this article's scope.
&lt;/div&gt;


&lt;h2&gt;Getting programmer friendly&lt;/h2&gt;

&lt;p&gt;Of course, it's always annoying to talk raw WSGI. You will forget some headers,
behave badly, kill people around you ... But we have installed a tool that will
transform the &lt;code&gt;environ&lt;/code&gt; dict into a nicely formated python object.&lt;/p&gt;

&lt;p&gt;Let me introduce my good friend &lt;code&gt;webob&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wsgi_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Create request from WSGI environment.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# A real app would look at the request before giving blind answers.&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Create a response&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hello, better world.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Communicate&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headerlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WSGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve_forever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is a bit better. But hey, we can then separate the WSGI stuff, and the
request-to-response process.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;web_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hello, nice world at &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wsgi_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Create the request&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Build a response from this request&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;web_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Communicate with gateway&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headerlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WSGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve_forever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Pythonize it&lt;/h2&gt;

&lt;p&gt;The good news is that the &lt;code&gt;webob&lt;/code&gt; library includes a decorator that is able to
turn any request-taking/response-returning python callable in a WSGI-capable
callable.&lt;/p&gt;

&lt;p&gt;The last version of this program, which does nothing more than the last one,
follows.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webob.dec&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgify&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@wsgify&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;Hello, short world at &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;wsgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WSGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve_forever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is all for today, but there is a lot more to come so stay tuned.&lt;/p&gt;

&lt;div class=&quot;zoom&quot;&gt;
  &lt;h4&gt;Related informations&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://github.com/rdconseil/wsgi-tutorial/tree/master/day1&quot;&gt;The code snippets on github&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://docs.webob.org/en/latest/index.html&quot;&gt;Webob documentation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.python.org/dev/peps/pep-0333/&quot;&gt;PEP 333&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.python.org/dev/peps/pep-3333/&quot;&gt;PEP 3333&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title><span class="headline">life</span> Champagne!</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/life/2011/08/20/champagne.html"/>
   <updated>2011-08-20T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/life/2011/08/20/champagne</id>
   <content type="html">&lt;p&gt;After a few years of thinking and about one year of getting things ready, I'm
glad to announce that my company is up since 1st of August.&lt;/p&gt;

&lt;p&gt;I will be doing a lot of things, but for the public part it's mostly around
git/sf2/python training and consulting. You can &lt;a
href=&quot;mailto:romain@dorgueil.net&quot;&gt;contact me&lt;/a&gt; for more informations.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title><span class="headline">dynamics</span> The end of Dynamics</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/dynamics/2011/08/19/end-of-dynamics.html"/>
   <updated>2011-08-19T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/dynamics/2011/08/19/end-of-dynamics</id>
   <content type="html">&lt;p&gt;For a few months, I did not have time to enhance dynamics. I'm currently
building up some exciting projects and this leaves me a very few time to invest
in &quot;just-for-fun&quot; stuff.&lt;/p&gt;

&lt;p&gt;Additionaly, the excellent assetic library (included in Symfony2 standard
distribution) does a very similar job (still I'm not sure it knows anything
about dependencies), but in a much more powerfull way. There is plenty of
gadgets and fancy stuff all around, and I'm sure you'll enjoy it.&lt;/p&gt;

&lt;p&gt;So hereby I decided to make official the end of my involvement in
sfDynamicsPlugin.&lt;/p&gt;

&lt;p&gt;The documentation website will stay up, but don't expect anything to come out.
Of course I cleaned up some blog articles about the dynamics releases, because
they became completely useless.&lt;/p&gt;

&lt;p&gt;R.I.P.&lt;/p&gt;

&lt;div class=&quot;info&quot;&gt;
    &lt;em&gt;08/23/2011 update&lt;/em&gt;
    &lt;p&gt;
        I got some e-mail and real life comments, so I'd like to clarify some
        points.
    &lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;
            For those who wonders, the code won't magically stop working
            because of my decision. It has been stable for a long period of
            time, and if you considered it safe to use yesterday, it is still
            today.
        &lt;/li&gt;
        &lt;li&gt;
            I also just pushed the &lt;a
            href=&quot;https://github.com/hartym/php-dynamics&quot;&gt;&quot;never-finished-1.0&quot;-code&lt;/a&gt;
            to github, which is plain nodeps PHP. You'll find drafts of
            frameworks adapters in the contrib directory (only sf1 adapter
            actually works). If it can be of any use, feel free to do whatever
            you please with it. You'll find the generated documentation (same
            state as lib) under &lt;a
            href=&quot;http://dynamics.dakrazy.net/1.0/html/index.html&quot;&gt; an obscure
            hidden directory on the dynamics website&lt;/a&gt;.
        &lt;/li&gt;
        &lt;li&gt;
            If someone thinks dynamics is enough usefull to deserve it and want
            to take over the project, I'll be glad to help.
        &lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title><span class="headline">database</span> Handling empty WHERE IN clauses in DBALs</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/database/2011/01/10/handling-empty-where-in-clauses-in-dbals.html"/>
   <updated>2011-01-10T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/database/2011/01/10/handling-empty-where-in-clauses-in-dbals</id>
   <content type="html">&lt;p&gt;I recently had a look at a project making heavy use of IN clauses. I'm not
advocating such an usage, as IN clauses can be pretty expensive, but there's
one special case that came to my concern. This case is the most trivial one in
the world, where the set we compare our value to is empty.&lt;/p&gt;

&lt;p&gt;Doctrine is translating empty &lt;code&gt;-&amp;gt;whereIn()&lt;/code&gt; clauses to exactly nothing,
resulting in having the pseudo request &lt;code&gt;SELECT * FROM user WHERE login in ();&lt;/code&gt;
into &lt;code&gt;SELECT * FROM user;&lt;/code&gt;. In my opinion, it's the exact opposite of what you
expect.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine_Core&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color = ?&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;whereIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$countries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This little snippet is getting a collection of fruits of a given color, and
coming from a list of countries. Actually, if the country list is empty, it
will return the whole list of fruits of &lt;code&gt;$color&lt;/code&gt;, completely skipping the
country part.&lt;/p&gt;

&lt;p&gt;I wondered a bit why this was, and talked some guys about it with who we agreed
it is a little weird. &lt;code&gt;x IN ()&lt;/code&gt; is invalid SQL, but deleting the clause to
avoid the error is not a solution.&lt;/p&gt;

&lt;p&gt;After a little chat about it with Jonathan, I decided to look some other ORMs
around, written in various languages. I already knew how Propel do handle the
problem, but I wanted to see other languages doing it. I opened SQLAlchemy and
django.db in Python and RubyOnRails / ARel in Ruby, to see what solution they
did adopt.&lt;/p&gt;

&lt;p&gt;The fun stuff is that they all used different solutions, so I thought it was
an interesting point to share.&lt;/p&gt;

&lt;h2&gt;Understanding the problem&lt;/h2&gt;

&lt;p&gt;The problem is not as easy at it may seem.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;x IN y&lt;/code&gt; statement can be nested in a complex expression, an it can also be
in a subquery used in a more complex query.&lt;/p&gt;

&lt;p&gt;For a simple &lt;code&gt;SELECT * FROM user WHERE user.id IN ()&lt;/code&gt;, you can be pretty
certain that the query won't return any result, and you should be able to
programmatically skip the query, as the logic of &quot;Give the users which ids are
within this empty set&quot; is of course easilly simplified to &quot;Give me no users
please&quot;.&lt;/p&gt;

&lt;p&gt;But for complex queries, you must replace this invalid SQL part by something
equivalent, to allow its usage within a superquery, or other complex statement.
This is what the majority of the ORMs out there are doing, except for django
which also has an elegant solution.&lt;/p&gt;

&lt;h2&gt;The quick and dirty hack - Propel 1.2/1.3&lt;/h2&gt;

&lt;div class=&quot;info&quot;&gt;
  I know it was done this way some years ago and did not want to investigate
  what is done in recent version of Propel. If some of you have the code
  examples, I'll be glad to add Propel 1.5/1.6 examples.
&lt;/div&gt;


&lt;p&gt;Propel does one of the simplest stuff. It replaces the &lt;code&gt;a IN ()&lt;/code&gt; part by &lt;code&gt;1 &amp;lt;&amp;gt;
1&lt;/code&gt;. Of course this will be false, and even if it's &quot;hackish&quot;, it works.&lt;/p&gt;

&lt;p&gt;It's important to note the result of &lt;code&gt;1&amp;lt;&amp;gt;1&lt;/code&gt; in SQL, which is &lt;code&gt;0&lt;/code&gt; (or maybe &lt;code&gt;false&lt;/code&gt;,
depending on implementations).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SELECT 1&amp;lt;&amp;gt;1;
+------+
| 1&amp;lt;&amp;gt;1 |
+------+
|    0 |
+------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;SQLAlchemy's solution&lt;/h2&gt;

&lt;p&gt;SQLAlchemy, a very popular and very powerfull python ORM, is doing yet another
hack of the same kind.&lt;/p&gt;

&lt;p&gt;What is great is that even if the part handling this case is hard to find, the
code itselfs consist about only of comments, so anybody can get it easily.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Special case handling for empty IN&amp;#39;s, behave like&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# comparison against zero row selectable.  We use != to&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# build the contradiction as it handles NULL values&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# appropriately, i.e. &amp;quot;not (x IN ())&amp;quot; should not return NULL&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# values for x.&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;The IN-predicate on &amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot; was invoked with an &amp;#39;&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&amp;#39;empty sequence. This results in a &amp;#39;&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&amp;#39;contradiction, which nonetheless can be &amp;#39;&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&amp;#39;expensive to evaluate.  Consider alternative &amp;#39;&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&amp;#39;strategies for improved performance.&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;a IN ()&lt;/code&gt; statement part is translated to &lt;code&gt;a &amp;lt;&amp;gt; a&lt;/code&gt;. What it does change
from the other hacks, is that the result value will be different wether &lt;code&gt;a&lt;/code&gt; is
defined or not.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SELECT 42 &amp;lt;&amp;gt; 42;
+----------+
| 42 &amp;lt;&amp;gt; 42 |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql&amp;gt; SELECT null &amp;lt;&amp;gt; 42;
+------------+
| null &amp;lt;&amp;gt; 42 |
+------------+
|       NULL |
+------------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It looks interesting, but I'm wondering if it's an accurate mimic of the
desired behaviour. We'll discuss this in the last chapter of this article.&lt;/p&gt;

&lt;h2&gt;The pythonic way - django.db&lt;/h2&gt;

&lt;p&gt;Django is the one that makes the less magic possible happen.&lt;/p&gt;

&lt;p&gt;It's easy, it does not translate the code into anything, it remains the invalid
&lt;code&gt;x IN ()&lt;/code&gt;. As the RDBMS won't be happy with this, it'll raise an exection. Same
behavior for SQL and ORM, nice and damn fuckin simple.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; IN (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field_sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;And the latest Ruby on Rails development does the same&lt;/h2&gt;

&lt;p&gt;Since I started to write this article, &lt;a
href=&quot;https://github.com/rails/arel/commit/1135c2c0884bfddffa39b784d71cd3fb22bd8988&quot;&gt;this
commit&lt;/a&gt; changed the way it's handled in RoR, and it's now doing the same
stuff as Django.&lt;/p&gt;

&lt;p&gt;It tried to do clever stuff before, and that was just &quot;looking&quot; clever, so I'm
pretty glad they changed this. If you're curious, you can read the new and old
code.&lt;/p&gt;

&lt;p&gt;As you may know, RubyOnRails has a relational algebra library named ARel, that
is able to parse a ruby query into an abstract syntax tree, and then compile it
into any query language, most probably some kind of SQL, but you can write
visitors to produce about anything.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Arel&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Visitors&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ToSql&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Arel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Visitors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Visitor&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# ... TRUNCATED ...&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;visit_Arel_Nodes_In&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; IN (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# ... TRUNCATED ...&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;br /&gt;




&lt;div class=&quot;zoom&quot;&gt;
  &lt;h4&gt;See also&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;a
      href=&quot;http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/&quot;&gt;Interesting
      article about the ARel rewrite for Rails3 by Aaron Patterson&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;a
      href=&quot;https://github.com/rails/arel/blob/master/lib/arel/visitors/to_sql.rb&quot;&gt;Read
      the full source code at github&lt;/a&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;


&lt;h2&gt;The (true, false, unknown) algebra&lt;/h2&gt;

&lt;p&gt;To understand all ORMs' solutions, we need to understand what &lt;code&gt;NULL&lt;/code&gt; means.&lt;/p&gt;

&lt;p&gt;What makes difference between everything here is that relational database
engines uses a ternary logic algebra instead of the regular boole's algebra to
evaluate logic statements.&lt;/p&gt;

&lt;p&gt;There are true values, false values, and unknown values. Logic tables are so
enhanced to use those &quot;new&quot; logical values.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;true AND unknown&lt;/code&gt; is &lt;code&gt;unknown&lt;/code&gt;, because the evaluation of the
right operand is required to know the expression's value. On the other hand,
&lt;code&gt;false AND unknown&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, because &lt;code&gt;false and anything&lt;/code&gt; is false. No need
to know the value of the right operand to know this.&lt;/p&gt;

&lt;p&gt;Looking at the following truth table will give you a good insight of this
logic.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
  &lt;tr&gt;&lt;th&gt;&lt;i&gt;A&lt;/i&gt;&lt;/th&gt;&lt;th&gt;&lt;i&gt;B&lt;/i&gt;&lt;/th&gt;&lt;th&gt;&lt;i&gt;A&lt;/i&gt; OR &lt;i&gt;B&lt;/i&gt;&lt;/th&gt;&lt;th&gt;&lt;i&gt;A&lt;/i&gt; AND &lt;i&gt;B&lt;/i&gt;&lt;/th&gt;&lt;th&gt;NOT &lt;i&gt;A&lt;/i&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;Unknown&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;False&lt;/td&gt;&lt;td&gt;True&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;


&lt;p&gt;&lt;em&gt;Source&lt;/em&gt;: wikipedia, &quot;ternary logic&quot; article.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The only conclusion I can come to is that amongst the ORMs I looked at, Django
and RoR are obviously correct.  Funny right? The only ones who are correct are
the ones which did not try to do anything clever or complicated.&lt;/p&gt;

&lt;p&gt;Strangely, the Propel hack seems to be correct too, but I'd like to have some
comments from database experts out there, because I'm still not 100% certain
about two points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Is my &lt;code&gt;( Unknown IN () ) == false&lt;/code&gt; assertion correct? I'm assuming that if
your question is &quot;Is this value present in this set, which is empty ?&quot;, the
answer is &quot;Definately not&quot;, and not &quot;I don't know&quot;, whether or not you know
the value of &quot;this&quot;. The doubt is in &quot;can this unknown be nothing at all&quot;?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does the concept of &quot;empty tuple&quot; makes an sense at all, from a relational
algebra point of view?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title><span class="headline">the roots</span> HTTP is the web's language</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/the-roots/2010/01/24/http-is-the-webs-language.html"/>
   <updated>2010-01-24T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/the-roots/2010/01/24/http-is-the-webs-language</id>
   <content type="html">&lt;p&gt;Everybody working in web development knows about this, right?&lt;/p&gt;

&lt;p&gt;I realized recently that it was far from being true. While frameworks and ORMs
make web developers' job easier and easier, more and more people comes to
develop websites without knowing about the real basics. They use relational
databases without knowing anything about SQL, and they develop websites without
understanding how the client will talk with their website.&lt;/p&gt;

&lt;p&gt;I don't pretend to make a revolution there, but if I bring my car to the car
mechanic, I hope he will know a bit more about it than &quot;engine makes power, and
so the car is working&quot;. So are my exigences when I ask a specialist to work on
a website.&lt;/p&gt;

&lt;p&gt;To give a parallel with playing music, you can learn to play some songs without
knowing anything about harmony and rhythm, but is you want to get serious about
what you play, it will become an absolute requirement.&lt;/p&gt;

&lt;p&gt;I so decided to make some short articles explaining in simple terms what those
basis are, to my humble opinion. First one is about HTTP.&lt;a hreflang=&quot;en&quot;
href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.3&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;So what is HTTP ?&lt;/h2&gt;

&lt;p&gt;HTTP is a &lt;strong&gt;communication protocol&lt;/strong&gt; that comes at
&lt;strong&gt;application level&lt;/strong&gt;. In easier terms, it means that it's a
language that allows two applications to communicate by exchanging
&lt;strong&gt;messages&lt;/strong&gt;. How those messages will transit between the two
applications is not HTTP purpose, and in a network-less world, you can even
imagine exchanging messages on floppy drives. In the real world, we prefer make
it transit over networks, using some low levels network protocols like TCP/IP.&lt;/p&gt;

&lt;p&gt;As it's true 99% of the time, we will assume it's always true: HTTP is the
communication language, TCP/IP will handle the transport of HTTP messages
between actors.&lt;/p&gt;

&lt;p&gt;Let's go back to the original definition.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;HTTP 1.1 (the last protocol version) is defined by &lt;a hreflang=&quot;en&quot;
href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616.html&quot;&gt;RFC 2616&lt;/a&gt;, which
says: The Hypertext Transfer Protocol (HTTP) is an application-level protocol
for distributed, collaborative, hypermedia information systems. HTTP has been
in use by the World-Wide Web global information initiative since 1990.&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;The HTTP protocol is a request/response protocol. A client sends a request to
the server in the form of a request method, URI, and protocol version,
followed by a MIME-like message containing request modifiers, client
information, and possible body content over a connection with a server. The
server responds with a status line, including the message's protocol version
and a success or error code, followed by a MIME-like message containing
server information, entity metainformation, and possible entity-body content.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This is the absolute minimum to know. HTTP is a communication language, and
works in a request-message, response-message way. This is extremely simple. The
RFC then explain that it can do much more complicated things, like handling
messages that will go through many nodes before reaching destination, but let's
keep it simple, and say that from a client or server point of view, it will
result in exactly the same thing.&lt;/p&gt;

&lt;p&gt;The RFC also makes clear that HTTP is not dependent on the transport mean:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;HTTP communication usually takes place over TCP/IP connections. The default
port is TCP 80, but other ports can be used. This does not preclude HTTP from
being implemented on top of any other protocol on the Internet, or on other
networks. HTTP only presumes a reliable transport; any protocol that provides
such guarantees can be used; the mapping of the HTTP/1.1 request and response
structures onto the transport data units of the protocol in question is
outside the scope of this specification.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;And it will be out of the scope of this blog post too. HTTP doesn't care about
how the message transport is done, but it's usually handled by TCP/IP.&lt;/p&gt;

&lt;h2&gt;Messages, requests, responses&lt;/h2&gt;

&lt;p&gt;So the basic communication tool will be &lt;strong&gt;messages&lt;/strong&gt;. A client to
server message is called a &lt;strong&gt;request&lt;/strong&gt;, and the server to client
&quot;answer&quot; is called a &lt;strong&gt;response&lt;/strong&gt;. Even if it may seems obvious, a
response cannot be the server initiative: a client must have made a request,
and server response is the response to this request.&lt;/p&gt;

&lt;p&gt;Now we're pretty confident about HTTP messages being Tupperware boxes
containing informations. Let's make a step forward and look at how this box
content is structured.&lt;/p&gt;

&lt;p&gt;Messages consists of three parts: the &lt;strong&gt;start line&lt;/strong&gt;, the
&lt;strong&gt;headers&lt;/strong&gt;, and the &lt;strong&gt;body&lt;/strong&gt;. As each part has
specific rules depending on if the message is a request or a response, we'll
have a look at both separately.&lt;/p&gt;

&lt;h3&gt;The request&lt;/h3&gt;

&lt;p&gt;The request start line is pretty easy to understand, it will tell the server
what we are requesting.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;GET /path/to/file/index.html HTTP/1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here it tells we're using HTTP GET method, to retrieve resource located at the
/path/to/file/index.html URI (uniform resource identifier). It also contains
what protocol variant we're using, to be sure we speak the exact same language.&lt;/p&gt;

&lt;p&gt;I will come back a bit later on what are &lt;strong&gt;HTTP methods&lt;/strong&gt;, and
will refer them as &quot;methods&quot; from now on.&lt;/p&gt;

&lt;p&gt;After this, the client will send the headers. Headers are a key-value list of
properties, that transmit various informations about the client, it's
capabilities, what it's expecting, and the message itself. I won't go over
every &lt;a hreflang=&quot;en&quot;
href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.3&quot;&gt;standard
request headers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Depending on what method is used, the request's body may or may not contain
data. For example, if we simply get google's homepage, it won't contain any
data. If we're uploading a file, or POST-ing form data to the server, the body
will be those data container.&lt;/p&gt;

&lt;h3&gt;The response&lt;/h3&gt;

&lt;p&gt;Once server received the request, it will pass it to a handler, which can be
about anything. In PHP applications, hosted on an apache server, chances are
that apache will call mod_php to handle the request, and build a response it
will send back to the client. But that's only one possibility amongst a huge
infinite list, which is outside the scope of this blog post.&lt;/p&gt;

&lt;p&gt;Anyway, the handler takes an http request as its input, and builds an http
response, starting by the response start line.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;HTTP/1.0 200 OK
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is a pretty standard response. Server starts by saying which protocol
variant it's using, then sends a computer readable status code, followed by an
human readable translation of this status code.&lt;/p&gt;

&lt;p&gt;A &lt;a hreflang=&quot;en&quot;
href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10&quot;&gt;complete
list of HTTP status codes&lt;/a&gt; is available at many places on the internet, and
it's useless to know them all. Googling &quot;http status code&quot; when you're looking
for the adequate status should be far enough.&lt;/p&gt;

&lt;p&gt;The most important thing to know is the different status code classes, defined
by the first digit of the code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1xx: Informational - Request received, continuing process.&lt;/li&gt;
  &lt;li&gt;2xx: Success - The action was successfully received, understood, and accepted.&lt;/li&gt;
  &lt;li&gt;3xx: Redirection - Further action must be taken in order to complete the request.&lt;/li&gt;
  &lt;li&gt;4xx: Client Error - The request contains bad syntax or cannot be fulfilled.&lt;/li&gt;
  &lt;li&gt;5xx: Server Error - The server failed to fulfill an apparently valid request.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Some practical direct application of this is when you need to choose between
sending back a 404 error and a 500 error. 404 is client's fault. He asked for
something that does not exist, and you tell him so. No problem. 500 means that
server tried hard to build a response, but something forbid it to achieve its
goal. This is a server-side application problem, and you should monitor, and
correct this as soon as possible.&lt;/p&gt;

&lt;p&gt;After sending the start line, the response, being a faithful HTTP message, will
go on by sending the headers. Like for the request, headers will give
informations about the server and the message content. You can consider it as
the README file that will help the &lt;strong&gt;user agent&lt;/strong&gt; (http client
software) to understand the response.&lt;/p&gt;

&lt;p&gt;Then, the response message will often contain a body (unless you're using some
method requiring not to have it), and the most seen cases are either HTML
content, XML/JSON (or similar) response that will be treated by a client-side
web application (flash, javascript, ...), or binary content (for a file
download, for example).&lt;/p&gt;

&lt;h2&gt;HTTP methods&lt;/h2&gt;

&lt;p&gt;What is it? Beside being one word in the request start line, the HTTP method is
the client's way to tell the server what kind of operation it wants to perform
on the resource requested. The method used in a request have direct
implications on what kind of work you can do server-side, and should be choosen
carefully (of course, you can break this rule, but it's a very bad idea).&lt;/p&gt;

&lt;h3&gt;Safe methods&lt;/h3&gt;

&lt;p&gt;Some methods are said &quot;safe&quot;. This means that request is a retrieval operation,
and should not do any other work. Notice that &quot;should&quot; does not mean &quot;must&quot;,
but user cannot be held responsible for breaking something if the method used
was &quot;safe&quot;.&lt;/p&gt;

&lt;p&gt;For example, you should not allow GET methods to create, delete or change
files, database records, or LDAP nodes (non exhaustive, of course).&lt;/p&gt;

&lt;p&gt;This is the case of GET and HEAD methods.&lt;/p&gt;

&lt;h3&gt;Idempotent methods&lt;/h3&gt;

&lt;p&gt;Idempotents methods are those which won't have any side-effect if repeated more
than once.&lt;/p&gt;

&lt;p&gt;For example, the DELETE method, which asks for a resource deletion, should have
the exact same effect if it's called only once on resource A, or if it's called
ten times. The overall effect should be the resource deletion (if allowed), not
less, not more.&lt;/p&gt;

&lt;p&gt;This is the case of GET, HEAD, PUT and DELETE methods.&lt;/p&gt;

&lt;h3&gt;Non-safe and non-idempotent methods&lt;/h3&gt;

&lt;p&gt;But of course, some requests needs to take risky and/or non-repeatable actions
server side. When an user agent uses such a method, he will be aware of the
risks.&lt;/p&gt;

&lt;p&gt;For example, POST-ing a comment will create a database record, and if you make
twice the same request (unless some protection has been developed to prevent
this), you will actually create two database records.&lt;/p&gt;

&lt;p&gt;It's the exact reason why browsers ask for user confirmation before repeating a
POST request, if user asks for a refresh. It's also the reason why you should
redirect to a safe idempotent resource after a successful form submission, to
forbid user to be able to repeat request.&lt;/p&gt;

&lt;p&gt;This is the case of POST method.&lt;/p&gt;

&lt;h3&gt;And the real world&lt;/h3&gt;

&lt;p&gt;All those methods are defined by the HTTP RFC, but the real world is much more
restricted than that. In fact, modern browsers only support GET and POST
methods, so you should only care about those.&lt;/p&gt;

&lt;p&gt;You should just keep in mind that other HTTP methods exist, and for example
HTTP extensions like WebDav (which is used by microsoft and their &quot;online
folders&quot;) use them. A simple way to try out PUT, DELETE, or any other method is
to use curl as an http client.&lt;/p&gt;

&lt;p&gt;To learn more about specificities of all methods, &lt;a hreflang=&quot;en&quot;
href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html&quot;&gt;you can still
refer to the original RFC&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Example&lt;/h3&gt;

&lt;h4&gt;The request...&lt;/h4&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;GET /index.html HTTP/1.1
Host: www.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Nothing complicated here, but for curious people (and you should be curious):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    example.com is &lt;a hreflang=&quot;en&quot;
    href=&quot;http://www.rfc-editor.org/rfc/rfc2606.txt&quot;&gt;a special domain reserved
    by the RFC 2606&lt;/a&gt;. This domain won't bring any conflict with a real
    domain, never. You should use it for all your tests and examples.
  &lt;/li&gt;
  &lt;li&gt;
    The &quot;Host&quot; header is required by HTTP 1.1 protocol, and is used by web
    servers to provide name based virtual hosting of different websites on the
    same IP address.
  &lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;and the response!&lt;/h4&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text&quot;&gt;HTTP/1.1 200 OK
Date: Sun, 24 Jan 2010 22:38:34 GMT
Server: Apache (Boubounetout/Linux)
Last-Modified: Fri, 01 Jan 2010 23:11:55 GMT
Etag: &amp;quot;f3f80-1b6-de1b034b&amp;quot;
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8

&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;Hello, world!&amp;lt;/p&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I hope that I'm far from being alone claiming that this is the very basis of
any serious web development, and that it will makes your web developer life
easier just because you understand the underlying communication language. Yes,
HTTP is definitely the web's language, and you should be aware of it.&lt;/p&gt;

&lt;p&gt;Ok folks, this will be all for today. But keep tuned, next episodes are already
in the pipes.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a hreflang=&quot;en&quot; href=&quot;http://www.funstaff.ch/&quot;&gt;Bertrand Zuchuat&lt;/a&gt;
for giving feedback and ideas before the article publication.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title><span class="headline">software</span> All about backward compatibility...</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/software/2009/09/23/all-about-backward-compatibility.html"/>
   <updated>2009-09-23T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/software/2009/09/23/all-about-backward-compatibility</id>
   <content type="html">&lt;p&gt;Backward compatibility sounds nice, but it's not so easy to respect it in big
projects. And the whole interest &lt;ins&gt;is&lt;/ins&gt; on big projects: it's maybe not
such a problem if your grand-ma's blog breaks its API on each release, but
there would be a revolution (or not?) if win32 API was changing on each
&lt;del&gt;enslavement&lt;/del&gt; service pack microsoft releases.&lt;/p&gt;

&lt;p&gt;Here is a real story case study of a BC break that happened on the PHP language
itself.&lt;/p&gt;

&lt;p&gt;It's always tempting to say &amp;laquo;hey, this feature is so great, and has so
little impact on the way it works, it may be cool to include it it the stable
branch, don't you think?&amp;raquo;. Well, it can be cool, if it cannot have any
effect on existing projects. But let's think again. How can it have no effect
on the existing projects? And if it has no effect, why include it in this
branch?&lt;/p&gt;

&lt;p&gt;I don't think there is a definite answer to this, as it &lt;ins&gt;may&lt;/ins&gt; have
pros sometimes. But most of the time, it will have much more cons than pros.
And if you doubt, forget it. Bigger is the project you work in, more it will
have users depending on it, and if there is any way users could have used the
old &quot;buggy&quot; feature, for sure they did.&lt;/p&gt;

&lt;p&gt;I want to expose some real life case that happened recently, on the PHP
distribution itself, showing its snowball effect through symfony to real life
projects.&lt;/p&gt;

&lt;p&gt;Let's have a look at &lt;a href=&quot;http://bugs.php.net/44144&quot; hreflang=&quot;en&quot;&gt;this php
bug report&lt;/a&gt;. It says &amp;laquo;spl_autoload_functions() should return object
instances, not class
names, when appropriate.&amp;raquo;&lt;/p&gt;

&lt;p&gt;Two words are really interesting in this bug report. It is &quot;should&quot; and &quot;when
appropriate&quot;. There is many assumptions behind this. When is this
&quot;appropriate&quot;? Why &quot;should&quot; it return instances? I would better rephrase it as
&amp;laquo;Feature request: spl_autoload_functions() must return object instances, as it
is more appropriate than strings containing class names.&amp;raquo;. The overall
formulation is not so much important as the facts that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is a feature request, not a bug&lt;/li&gt;
&lt;li&gt;The function is currently working, but its behaviour can be changed to a
more convenient one.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;But it's ok, right? The target version was 5.3 while still no stable releases
existed.&lt;/p&gt;

&lt;p&gt;Yes it is.&lt;/p&gt;

&lt;p&gt;Oh wait, let's read the comments now.&lt;/p&gt;

&lt;p&gt;&amp;laquo;Thanks for the fix. Do you think, by any chance, we can sneak this into PHP
5.2, or is that impossible?&amp;raquo;&lt;/p&gt;

&lt;p&gt;The definite answer to this question should be &amp;laquo;It is actually impossible.
Introducing a behavior change into 5.2 (years) stable release would break
backward compatibility.&amp;raquo;&lt;/p&gt;

&lt;p&gt;And the patch made it to PHP 5.2.11.&lt;/p&gt;

&lt;p&gt;Is there any consequences? Yes of course. In fact any symfony 1.3 projects were
broken at this stage, because symfony used this behaviour with the reintroduced
sfAutoloadAgain autoloader, which checked the return value for strings, and got
instances, causing an infinite loop that made apache segmentation fault.&lt;/p&gt;

&lt;p&gt;This is now fixed, by &lt;a href=&quot;http://trac.symfony-project.org/changeset/22248&quot;
title=&quot;http://trac.symfony-project.org/changeset/22248&quot;&gt;http://trac.symfony-project.org/cha...&lt;/a&gt;,
but was the feature worth the hassle? How many projects can this kind of change
break?&lt;/p&gt;

&lt;p&gt;So for all you that work on big projects, think well, then think again, then
don't do such a change. Usual formula says &amp;laquo;With great power comes great
responsibilities&amp;raquo;. I'd add &amp;laquo;Great notoriety induce great
responsibilities&amp;raquo;.&lt;/p&gt;

&lt;p&gt;Yes millions of people uses PHP, and that's the main reason why stable branch
should stay stable. Rock solid stable.&lt;/p&gt;

&lt;p&gt;And it's the same reason why symfony branches stay stable, as much as possible.
And any exception to this always have bad feedback.&lt;/p&gt;

&lt;p&gt;(thanks to &lt;a href=&quot;http://blog.thepimp.net/&quot;&gt;Pierre Joye&lt;/a&gt; for his reminder
at &lt;a href=&quot;http://news.php.net/php.internals/45628&quot;
title=&quot;http://news.php.net/php.internals/45628&quot;&gt;http://news.php.net/php.internals/4...&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: Software stability does not only mean bug-free. It
also means &amp;laquo;not changing&amp;raquo;, and it's the main definition used there.
Bugs are annoying, but they can be fixed to get the wanted behavior back, so
it's not a problem. And the only wanted behavior of a stable piece of software
is the behavior it always had.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title><span class="headline">symfony</span> How to render a component in an action with symfony 1.1+</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/symfony/2009/03/12/how-to-render-a-component-in-an-action-with-symfony-1-1.html"/>
   <updated>2009-03-12T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/symfony/2009/03/12/how-to-render-a-component-in-an-action-with-symfony-1-1</id>
   <content type="html">

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;executeBarfoo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sfWebRequest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;renderComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my_module&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;my_component&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title><span class="headline">database</span> Foreign key's onDelete for dummies</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/database/2008/07/10/foreign-keys-ondelete-for-dummies.html"/>
   <updated>2008-07-10T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/database/2008/07/10/foreign-keys-ondelete-for-dummies</id>
   <content type="html">&lt;p&gt;Any modern relational database engine supports the onDelete and onUpdate
attributes on foreign keys. Propel and Doctrine of course allows to define it
in the schema file (yaml or xml) and I believe it is important to explicitly
set it.&lt;/p&gt;

&lt;h2&gt;Restrict mode&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&amp;laquo;Better do nothing than something stupid.&amp;raquo;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The default behaviour is &lt;em&gt;ON DELETE RESTRICT&lt;/em&gt;. This is the most secure
setting, so it is normal to have it as default.&lt;/p&gt;

&lt;p&gt;If we try to &lt;em&gt;DELETE&lt;/em&gt; a record referenced by the current object, the
database engine just raise an SQL error. If it was not an error to
&lt;em&gt;DELETE&lt;/em&gt; this, you will have to start by removing the linked object, or
setting the foreign key value to something different.&lt;/p&gt;

&lt;h2&gt;Cascade mode&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&amp;laquo;No need to keep obsolete things.&amp;raquo;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But our database engines are able to do better. For example, if you have an
user's settings table and you delete an user, you may not wan't
to keep his settings. You just set &lt;em&gt;ON DELETE CASCADE&lt;/em&gt; on user's setting
foreign key column referencing the user table, and if a user is ever deleted,
all his associated properties will be destroyed.&lt;/p&gt;

&lt;p&gt;Along with &lt;em&gt;ON DELETE CASCADE&lt;/em&gt;, we usually add a &lt;em&gt;NOT NULL&lt;/em&gt;
constraint (or required: true), as the existence of current object is directly
related to the existence of linked object. This may be wrong from time to time,
but it is usually the case.&lt;/p&gt;

&lt;h2&gt;Set null mode&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&amp;laquo;We don't rely on this. Just forget it.&amp;raquo;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The last behavior is the &lt;em&gt;ON DELETE SET NULL&lt;/em&gt; option. It does exactly
what it says. If linked object is removed, we set our foreign key value to
null.&lt;/p&gt;

&lt;p&gt;This the behavior you may want to use for articles having a link to their
author for example. If the author is removed from database, we don't want to
delete his articles, so we just loose the author information (well ok, this is
a simplification, but it basically shows the idea).&lt;/p&gt;

&lt;h2&gt;Why I think we should explicitly use it&lt;/h2&gt;

&lt;p&gt;The default database engine behavior is &amp;laquo;I don't know how to handle
it&amp;raquo;.  Setting it will add power to your database model, while taking
profit of your RDBMS features. Not setting it is like saying &amp;laquo;I don't
know which way I want my database to behave in case we delete a linked
object&amp;raquo;, and that's like saying &amp;laquo;I don't know how I want my model
to react&amp;raquo;. Thinking a little to understand which way you want it to work
will make you certain you're understanding the behavior you need in your
project.&lt;/p&gt;

&lt;h2&gt;How to set it in your favorite ORM&lt;/h2&gt;

&lt;h3&gt;schema.yml with Doctrine&lt;/h3&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;l-Scalar-Plain&quot;&gt;string(255)&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;string(4096)&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;integer(4)&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;relations&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;l-Scalar-Plain&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;CASCADE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;PHP model with Doctrine&lt;/h3&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasOne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;User&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;local&amp;#39;&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;user_id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                              &lt;span class=&quot;s1&quot;&gt;&amp;#39;foreign&amp;#39;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                              &lt;span class=&quot;s1&quot;&gt;&amp;#39;onDelete&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;CASCADE&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;schema.yml with Propel&lt;/h3&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;data_id&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;integer&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;primaryKey&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foreignTable&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foreignReference&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cascade&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;onUpdate&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cascade&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;schema.xml with Propel&lt;/h3&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;foreign-key&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;foreignTable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;data&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onDelete =&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;setnull&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;reference&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;local=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;data_id&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;foreign=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/foreign-key&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title><span class="headline">symfony</span> Overview of symfony 1.1 event dispatcher</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/symfony/2008/04/30/overview-of-symfony-1-1-event-dispatcher.html"/>
   <updated>2008-04-30T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/symfony/2008/04/30/overview-of-symfony-1-1-event-dispatcher</id>
   <content type="html">&lt;p&gt;As you may now by now, Symfony 1.1 introduces a new powerfull event dispatcher
inspired by Apple Cocoa's NotificationCenter. Basically, it allows any entity
to &quot;listen&quot; to events, and get a call on the registered callback if this event
ever happens.&lt;/p&gt;

&lt;p&gt;Symfony 1.1 provides &lt;a
href=&quot;http://www.symfony-project.org/book/1_1/17-Extending-Symfony#chapter_17_sub_built_in_events&quot; hreflang=&quot;en&quot;&gt;some
default events&lt;/a&gt; you can listen to, but of course you can create your own
events if you need.&lt;/p&gt;

&lt;h2&gt;Listen to an event&lt;/h2&gt;

&lt;p&gt;To listen to an event, you need to use the &quot;connect&quot; method on the event
dispatcher instance. The first parameter is the event name, and the second is a
PHP callable that will get called if the event happens.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$dispatcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;user.change_culture&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;listenToChangeCultureEvent&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Create a custom event&lt;/h2&gt;

&lt;p&gt;To use the dispatcher for your own needs, you just need to define your event
name in your project specifications, and send notifications to it. Depending on
the behaviour needed, three options are offered:&lt;/p&gt;

&lt;h3&gt;Simple notifications&lt;/h3&gt;

&lt;p&gt;The simpliest way is to notify all listeners with the &lt;code&gt;-&amp;gt;notify()&lt;/code&gt; method.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$dispatcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;my.super.cool.event&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h3&gt;Notifications until something&lt;/h3&gt;

&lt;p&gt;Sometimes, you prefer to notify all listeners until one says &quot;Ok guys, I
handled this one. Don't worry about it anymore&quot;.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$dispatcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;notifyUntil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;my.super.cool.event&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The first listener that will return non-false value will stop the event chain.&lt;/p&gt;

&lt;h3&gt;Filtering notifications&lt;/h3&gt;

&lt;p&gt;The last notifying method is called filtering. You set this up when you want to
permit anything to act as a filter on something, meaning any listener can
modify a source object.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$dispatcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;my.super.cool.event&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$objectToFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Every listener must return the filtered value (or the original object if
nothing was done) to pass to the next listener.&lt;/p&gt;

&lt;h2&gt;Practical use: Register routes in your plugins&lt;/h2&gt;

&lt;p&gt;One of the first practical applications that came to me was the new way of
registering routes in plugins. In symfony 1.0, a coincidence made possible to
use the routing in a plugin's config.php but that's not possible anymore in
symfony 1.1, so you have to use the event dispatcher. To accomplish this, we're
going to set up a &lt;code&gt;routing.load_configuration&lt;/code&gt; listener in the plugin's
config.php:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dispatcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;routing.load_configuration&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myPluginRouting&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;listenToRoutingLoadConfigurationEvent&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Then you just need to create the callback class/method:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;myPluginRouting&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;sd&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;   * Listens to the routing.load_configuration event.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;   *&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;   * @param sfEvent An sfEvent instance&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;listenToRoutingLoadConfigurationEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sfEvent&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// preprend our routes&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;prependRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my_route&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/my_plugin/:action&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;module&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;myPluginAdministrationInterface&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here we go :-D&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title><span class="headline">symfony</span> Don't be fooled by awkward view.yml js/css positionning syntax!</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/symfony/2008/04/21/dont-be-fooled-by-awkward-view-yml-jscss-positionning-syntax.html"/>
   <updated>2008-04-21T00:00:00+02:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/symfony/2008/04/21/dont-be-fooled-by-awkward-view-yml-jscss-positionning-syntax</id>
   <content type="html">&lt;p&gt;Short post today about advanced view.yml configuration (in symfony 1.0, and
1.1) for assets.&lt;/p&gt;

&lt;p&gt;You can give additional options to &lt;code&gt;javascripts:&lt;/code&gt; and &lt;code&gt;stylesheets:&lt;/code&gt; sections,
but the sin equa non condition is to know about the yet very un-documented
view.yml assets syntax.&lt;/p&gt;

&lt;p&gt;So here it is:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;javascripts&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;jquery&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;stylesheets&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mycss&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p-Indicator&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I don't know if there are others options like thoose available, but taken the
'position' attribute apart, which is extracted to become the &lt;code&gt;$position&lt;/code&gt; method
argument of &lt;code&gt;sfWebResponse::addJavascript()&lt;/code&gt; and
&lt;code&gt;sfWebResponse::addStylesheet()&lt;/code&gt;, any other option is passed in the &lt;code&gt;$options&lt;/code&gt;
array.&lt;/p&gt;

&lt;p&gt;Methods prototypes below:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;sfWebResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addJavascript&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addStylesheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title><span class="headline">symfony plugins</span> Complex relations population in propel 1.2 / 1.3</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/symfony-plugins/2008/01/31/complex-relations-population-in-propel.html"/>
   <updated>2008-01-31T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/symfony-plugins/2008/01/31/complex-relations-population-in-propel</id>
   <content type="html">&lt;div class=&quot;warning&quot;&gt;
  This plugin is mostly a workaround for propel 1.2/1.3 limitations. If it's an
  option, you should consider using &lt;a
  href=&quot;http://www.propelorm.org/wiki/Documentation/1.5&quot;&gt;Propel 1.5&lt;/a&gt;
  instead.
&lt;/div&gt;


&lt;p&gt;Since quite a bit of time, I've been faced with an annoying problem on every
projects I use propel on. Propel builders only generates some specific cases
selection methods, which consists of pretty ugly copy paste of the same code to
populate the objects, and if your needs are not satisfied by the finite little
number of propel handled cases, you'll have to either use pure SQL, or write a
custom doSelect method. That seems okay at first sight, but it is not. In fact,
you're about copypasting the propel generated method, and that's a rude
violation of D.R.Y. principle.&lt;/p&gt;

&lt;p&gt;I found no solutions during the two last years, but maybe things will change
soon with the new sfPropelImpersonatorPlugin. This plugin is aiming at doing
arbitrary object population based on informations provided by propel's
introspection methods (DatabaseMap/TableMap/ColumnMap) to link populated
objects.&lt;/p&gt;

&lt;p&gt;The plugin is currently in very early stage, but is working pretty well for my
needs, and I'm looking forward to know what others are thinking about it.&lt;/p&gt;

&lt;div class=&quot;zoom&quot;&gt;
  &lt;h4&gt;Related informations&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://dakrazy.net/documents/sfPropelImpersonatorPlugin&quot; hreflang=&quot;en&quot;&gt;sfPropelImpersonatorPlugin documentation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://trac.symfony-project.com/wiki/sfPropelImpersonatorPlugin&quot; hreflang=&quot;en&quot;&gt;sfPropelImpersonatorPlugin README&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://trac.symfony-project.com/browser/plugins/sfPropelImpersonatorPlugin/trunk&quot; hreflang=&quot;php&quot;&gt;Browse the source&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.propelorm.org/wiki/Documentation/1.5&quot;&gt;Propel 1.5 documentation / website&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title><span class="headline">symfony plugins</span> Using symfony forms before 1.1</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/symfony-plugins/2008/01/07/using-symfony-forms-before-1-1.html"/>
   <updated>2008-01-07T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/symfony-plugins/2008/01/07/using-symfony-forms-before-1-1</id>
   <content type="html">&lt;p&gt;The new symfony 1.1 form/validation framework is 100% symfony-independant, and
though is not limited to the (very) awaited 1.1 stable release. To use it in
your own symfony 1.0 projects, you can use sfForms11Plugin. It's content is
very thin: it only sets up externals to symfony 1.1 form/widget/validator
libraries.&lt;/p&gt;

&lt;p&gt;To use it, simply add the following external to your project:&lt;/p&gt;

&lt;pre&gt;
sfForms11Plugin http://svn.symfony-project.com/plugins/sfForms11Plugin
&lt;/pre&gt;


&lt;p&gt;Or check it out from your project base directory:&lt;/p&gt;

&lt;pre&gt;
svn co http://svn.symfony-project.com/plugins/sfForms11Plugin plugins/sfForms11Plugin
&lt;/pre&gt;


&lt;h2&gt;Let's try it...&lt;/h2&gt;

&lt;p&gt;Now you'll be able to define sfForm sub-classes to materialize forms:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HelloWorldForm&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfForm&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setWidgetSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfWidgetFormSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfWidgetFormInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setValidatorSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfValidatorSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s1&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfValidatorString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;required&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;min_length&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;max_length&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;widgetSchema&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setNameFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hello[%s]&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;errorSchema&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfValidatorErrorSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;validatorSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This class define the model of your HelloWorldForm, and you can now use it in
your actions:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;testActions&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfActions&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;executeHelloWorld&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HelloWorldForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$hello&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRequestParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;@hello?name=&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;At this point, the only little detail still missing is the view:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;method=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php echo $form; ?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;colspan=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;align=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;submit&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Greetings, Mr Computer!&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;That's it! You now have a simple form, self-validating, protected against CSRF
attacks and redirecting to some place if values entered matched our
sfValidatorSchema.&lt;/p&gt;

&lt;div class=&quot;zoom&quot;&gt;
  &lt;h4&gt;Related informations&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://trac.symfony-project.com/wiki/sfForms11Plugin&quot; hreflang=&quot;en&quot;&gt;sfForms11 on symfony-project.org&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Cross-site_request_forgery&quot; hreflang=&quot;en&quot;&gt;About CSRF attacks&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title><span class="headline">symfony</span>Creating custom config handlers</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/symfony/2007/12/24/creating-custom-config-handlers-in-symfony-1-0.html"/>
   <updated>2007-12-24T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/symfony/2007/12/24/creating-custom-config-handlers-in-symfony-1-0</id>
   <content type="html">&lt;div class=&quot;warning&quot;&gt;
  This article was written for symfony 1.0 and pre-1.0.
  &lt;br /&gt;&lt;br /&gt;
  You most probably will have to adapt the code.
&lt;/div&gt;




&lt;p&gt;When writing plugins, you often want to do it the symfony way, by putting
configuration stuff in YAML files to allow the final user to override your
default values in a harmless way.&lt;/p&gt;




&lt;p&gt;To do this, the correct way is to create a config handler, extending
sfConfigHandler, or its child class sfYamlConfigHandler.&lt;/p&gt;




&lt;p&gt;Here is a simple one, just dumping YAML data found in your config file into
an sfConfig::get()-able PHP dataset.&lt;/p&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;myStupidConfigHandler&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfYamlConfigHandler&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$configFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// retrieve yaml data&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parseYamls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$configFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;?php&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                    &lt;span class=&quot;s2&quot;&gt;&amp;quot;// auto-generated by myStupidConfigHandler&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                    &lt;span class=&quot;s2&quot;&gt;&amp;quot;// date: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                    &lt;span class=&quot;s2&quot;&gt;&amp;quot;sfConfig::set(&amp;#39;my_stupid_config_entry&amp;#39;, %s);&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Y-m-d H:i:s&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;var_export&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;We can enhance it, taking care of symfony environments.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;myStupidConfigHandler&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfYamlConfigHandler&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$configFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// retrieve yaml data&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parseYamls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$configFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// get current environment&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;sf_environment&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// merge default and environment specific config&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfToolKit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;arrayDeepMerge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;all&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;all&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;?php&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                    &lt;span class=&quot;s2&quot;&gt;&amp;quot;// auto-generated by myStupidConfigHandler&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                    &lt;span class=&quot;s2&quot;&gt;&amp;quot;// date: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                    &lt;span class=&quot;s2&quot;&gt;&amp;quot;sfConfig::set(&amp;#39;my_stupid_config_entry&amp;#39;, %s);&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Y-m-d H:i:s&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;var_export&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Next step will be to tell symfony which configuration file patterns should
be loaded using our class. To do this, add the following entry to
config/config_handlers.yml (whether in your app, plugin or module, depending on
the scope of your config handler)&lt;/p&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;yaml&quot;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;config/stupid.yml&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;l-Scalar-Plain&quot;&gt;myStupidConfigHandler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Once this is done, the very little remaining last step is to mak sure you
include the compiled yml.php file with the following magic command, that will
rebuild it when unexistant or outdated:&lt;/p&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sfConfigCache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;checkConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;config/stupid.yml&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$stupid_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sfConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my_stupid_config_entry&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;easy one :-)&lt;/p&gt;




&lt;div class=&quot;zoom&quot;&gt;
  &lt;h4&gt;Related informations&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.yaml.org/&quot;&gt;YAML Ain't Markup Language - YAML Reference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.symfony-project.org/api/1_0/sfConfigHandler&quot;&gt;symfony apidoc: sfYamlConfig&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.symfony-project.org/api/1_0/sfYamlConfigHandler&quot;&gt;symfony apidoc: sfYamlConfigHandler&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title><span class="headline">doctrine</span> Using DBMS functions with sfDoctrine</title>
   <link href="http://romain.dorgueil.net/blog/blog/en/doctrine/2007/10/30/using-dbms-functions-with-sfdoctrine.html"/>
   <updated>2007-10-30T00:00:00+01:00</updated>
   <id>http://romain.dorgueil.net/blog/blog/en/doctrine/2007/10/30/using-dbms-functions-with-sfdoctrine</id>
   <content type="html">&lt;div class=&quot;warning&quot;&gt;
  This article was written for early PHP-Doctrine versions (1.0 or before).
  &lt;br /&gt;&lt;br /&gt;
  It may not be useable with recent doctrine versions (and most probably not at
  all with Doctrine 2.0).
&lt;/div&gt;


&lt;p&gt;I recently had a peek on symfony forum, and seen someone asking &quot;How can I
make a SELECT count(*) FROM .... with doctrine?&quot;.&lt;/p&gt;

&lt;p&gt;An answer to such a question should be pretty obvious as it's of everyday use,
but the question seems to have come to life many times as well on IRC than on
the forum/mailing list.&lt;/p&gt;

&lt;p&gt;Here is my two-cents how-to.&lt;/p&gt;

&lt;h2&gt;Using builtin DQL aggregate functions&lt;/h2&gt;

&lt;p&gt;Basically, you can add aggregate functions (functions that operates on a group
of records instead of one record, also called GROUP BY functions) to your DQL
query the same way you'd do in SQL, provided the fact you're using one of the
builtin DQL aggregate functions (COUNT, MAX, MIN, AVG, SUM).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine_Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;COUNT(t.id) cnt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Table t&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFirst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;cnt&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Using DBMS specific aggregate functions&lt;/h2&gt;

&lt;p&gt;If the function you need is in the list, no need to go further. But some
functions are DBMS specific, for example MySQL provides a
&lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat&quot;&gt;GROUP_CONCAT()&lt;/a&gt;
function. It would be nonsense for DQL to provide that, as it would not be
translatable in some of the other DBMS SQL, but it would also be nonsense to
restrict functionalities to the smallest common functionnalities set of every
DBMS that Doctrine supports.&lt;/p&gt;

&lt;p&gt;The way to go is to change the &lt;a href=&quot;http://www.doctrine-project.org/documentation/manual/1_0/en/configuration#portability&quot;&gt;portablility
level&lt;/a&gt;
of doctrine, to match your needs. As the name implies, you're loosing in
portability between the different DBMS, but you're gaining specific
functionnalities of yours.&lt;/p&gt;

&lt;p&gt;The following code, running in &lt;code&gt;PORTABILITY_ALL&lt;/code&gt; mode, will throw a Doctrine_Query_Exception:&lt;/p&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Doctrine_Manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ATTR_PORTABILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PORTABILITY_ALL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine_Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;GROUP_CONCAT(t.value) concatedstring&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Table t&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFirst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now remove the &lt;code&gt;Doctrine::PORTABILITY_EXPR&lt;/code&gt; bit to this attribute, and you will
get the correct result (using MySQL):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Doctrine_Manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ATTR_PORTABILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PORTABILITY_ALL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PORTABILITY_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine_Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;GROUP_CONCAT(t.value) concatedstring&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Table t&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFirst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;concatedstring&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Extending to other functions&lt;/h2&gt;

&lt;p&gt;Ok aggregate functions are usefull, but other functions can be very handy too,
&lt;a href=&quot;http://www.doctrine-project.org/projects/orm/1.2/docs/manual/dql-doctrine-query-language/en#functional-expressions:string-functions&quot;&gt;string
functions&lt;/a&gt;
for example. Doctrine manual tells us that builtin DQL string functions are
&lt;code&gt;CONCAT&lt;/code&gt;, &lt;code&gt;SUBSTRING&lt;/code&gt;, &lt;code&gt;TRIM&lt;/code&gt;, &lt;code&gt;LOWER&lt;/code&gt;, &lt;code&gt;UPPER&lt;/code&gt;, &lt;code&gt;LOCATE&lt;/code&gt; and &lt;code&gt;LENGTH&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Doctrine_Manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ATTR_PORTABILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PORTABILITY_ALL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine_Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;LENGTH(t.value) val_len, t.value&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Test t&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$results&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39; =&amp;gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;val_len&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This code will display all records' value fields, followed by their
character length computed by the DBMS, in &lt;code&gt;PORTABILITY_ALL&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;Now let's say you want to use
&lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_bit-length&quot;&gt;BIT_LENGTH()&lt;/a&gt;
MySQL function...&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Doctrine_Manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ATTR_PORTABILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PORTABILITY_ALL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PORTABILITY_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Doctrine_Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;BIT_LENGTH(t.value) val_len, t.value&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Test t&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$results&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39; =&amp;gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;val_len&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is the way to go again.&lt;/p&gt;

&lt;p&gt;No need to say, this extends to every type of functions available in the
different DBMS.&lt;/p&gt;
</content>
 </entry>
 

</feed>

