<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://prendreuncafe.com/blog/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Prendre un Café - Tag - sql</title>
  <link>http://prendreuncafe.com/blog/</link>
  <atom:link href="http://prendreuncafe.com/blog/feed/tag/sql/rss2" rel="self" type="application/rss+xml"/>
  <description></description>
  <language>fr</language>
  <pubDate>Tue, 01 Feb 2011 14:49:24 +0100</pubDate>
  <copyright>Contenus sous licence Creative Commons BY-SA</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Optimize your Doctrine Workflow with Specialized Queries</title>
    <link>http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries</link>
    <guid isPermaLink="false">urn:md5:07be0ff35e1f2e047f2faca25323c26e</guid>
    <pubDate>Tue, 15 Sep 2009 19:14:00 +0200</pubDate>
    <dc:creator>NiKo</dc:creator>
        <category>Dev</category>
        <category>bestpractices</category><category>doctrine</category><category>php</category><category>query</category><category>sql</category><category>symfony</category><category>tips</category>    
    <description>    &lt;p&gt;I&amp;#8217;m currently working on a big &lt;a href=&quot;http://www.symfony-project.org/&quot; hreflang=&quot;en&quot;&gt;Symfony&lt;/a&gt; project, with a lot of &lt;a href=&quot;http://www.doctrine-project.org/&quot; hreflang=&quot;en&quot;&gt;Doctrine&lt;/a&gt; models and complex queries to write. I found a way to organize all of them in an object-oriented and cleaner way than using the traditionnal &lt;code&gt;addNamedQuery()&lt;/code&gt; and &lt;code&gt;createNamedQuery()&lt;/code&gt; methods workflow&lt;sup&gt;[&lt;a href=&quot;http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#pnote-1123-1&quot; id=&quot;rev-pnote-1123-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;


&lt;p&gt;The idea is to create dedicated &lt;a href=&quot;http://www.doctrine-project.org/Doctrine_Query/1_2&quot; hreflang=&quot;en&quot;&gt;query&lt;/a&gt; classes for a given model&amp;#160;; this way, you can provide useful methods to build the business-related parts of your query.&lt;/p&gt;


&lt;p&gt;As usual, the theory is more understandable with a concrete example. Let&amp;#8217;s consider this simple Doctrine model&lt;sup&gt;[&lt;a href=&quot;http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#pnote-1123-2&quot; id=&quot;rev-pnote-1123-2&quot;&gt;2&lt;/a&gt;]&lt;/sup&gt;&amp;#160;:&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; The provided examples have been written in a hurry, so mistakes might have been not detected by my attentive proof-reading &lt;img src=&quot;/blog/themes/battlestar/smilies/wink.gif&quot; alt=&quot;;)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;

&lt;pre&gt; yaml
BlogAuthor:
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true  
    name:
      type: string(255)
  relations:
    Post:
      type: one
      class: BlogPost
      local: id
      foreign: author_id

BlogPost:
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    author_id:
      type: integer(4)
      notnull: true
    title:
      type: string(255)
    content:
      type: string(65535)
  relations:
    Author:
      type: one
      class: BlogAuthor
      local: author_id
      foreign: id
    Comments:
      type: many
      class: BlogComment
      local: id
      foreign: post_id

BlogComment:
  columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    post_id:
      type: integer(4)
      notnull: true
    author:
      type: string(255)
    content:
      type: string(5000)
  relations:
    Post:
      type: one
      class: BlogPost
      local: post_id
      foreign: id
&lt;/pre&gt;


&lt;p&gt;Now let&amp;#8217;s imagine a Query class dedicated to query the BlogPost table:&lt;/p&gt;

&lt;pre&gt; php
&amp;lt;?php 
class BlogPostQuery extends Doctrine_Query
{
  static public function create($conn = null, $class = null)
  {
    return parent::create($conn, 'BlogPostQuery')
      -&amp;gt;from('BlogPost p');
  }
  
  public function addPosts($fields = 'p.*')
  {
    return $this-&amp;gt;addSelect('p.*');
  }
  
  public function addComments($fields = 'c.*')
  {
    return $this
      -&amp;gt;addSelect($fields)
      -&amp;gt;leftJoin('p.Comments c')
      -&amp;gt;addGroupBy('c.id');
  }
  
  public function addAuthors($fields = 'a.*')
  {
    return $this
      -&amp;gt;addSelect($fields)
      -&amp;gt;leftJoin('p.Author a')
      -&amp;gt;addGroupBy('a.id');
  }
  
  public function addCommentsCount($alias = 'nb_comments')
  {
    return $this
      -&amp;gt;addSelect(sprintf('COUNT(c.id) as %s', $alias))
      -&amp;gt;addGroupBy('c.id');
  }
  
  public function filterByAuthorName($authorName)
  {
    return $this
      -&amp;gt;andWhere('a.name = ?', $authorName);
  }
}
&lt;/pre&gt;


&lt;p&gt;So how can we use this query object? Here are some sample uses:&lt;/p&gt;

&lt;pre&gt; php
// Retrieve all posts
$posts = BlogPostQuery::create()
  -&amp;gt;addPosts()
  -&amp;gt;fetchArray();

// Retrieve all posts with comments
$posts = BlogPostQuery::create()
  -&amp;gt;addPosts()
  -&amp;gt;addComments()
  -&amp;gt;fetchArray();

// Retrieve all posts with comments and their count per post
$posts = BlogPostQuery::create()
  -&amp;gt;addPosts()
  -&amp;gt;addComments()
  -&amp;gt;addCommentsCount('yataa')
  -&amp;gt;fetchArray();

// Retrieve all post with chuck as its author and related comments
$posts = BlogPostQuery::create()
  -&amp;gt;addAuthors()
  -&amp;gt;addPosts()
  -&amp;gt;addComments()
  -&amp;gt;filterByAuthorName('chuck')
  -&amp;gt;fetchArray();

// and so on...
&lt;/pre&gt;


&lt;p&gt;Of course, this example of use is not really relevant as our model is really simple, but when you&amp;#8217;re dealing with dozens of internationalized objects, it can help cleaning your model classes, controllers and improving the organization of your work.&lt;/p&gt;


&lt;h3&gt;Update and important precisions&lt;/h3&gt;


&lt;p&gt;Some people are having negative feedback regarding this technique, claiming it will encourage people using the custom query object directly in the controllers; that&amp;#8217;s absolutely not the case as the queries are to be used only within the model layer, for example in the &lt;code&gt;BlogPostTable&lt;/code&gt; class:&lt;/p&gt;

&lt;pre&gt; php
&amp;lt;?php
class BlogPostTable extends Doctrine_Table
{
  static public function getPostsWithCommentsByAuthor($authorName)
  {
    return BlogPostQuery::create()
      -&amp;gt;addPosts()
      -&amp;gt;addComments()
      -&amp;gt;filterByAuthorName($authorName)
      -&amp;gt;fetchArray()
    ;
  }
}
&lt;/pre&gt;


&lt;p&gt;And in a controller:&lt;/p&gt;

&lt;pre&gt; php
class blogActions extends sfActions
{
  public function executeListByAuthor(sfWebRequest $request)
  {
    $this-&amp;gt;posts = BlogPostTable::getPostsWithCommentsByAuthor($request-&amp;gt;getParameter('author'));
  }
}
&lt;/pre&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#rev-pnote-1123-1&quot; id=&quot;pnote-1123-1&quot;&gt;1&lt;/a&gt;] &amp;#8230; or raw queries written directly within controllers, but you may know that &lt;a href=&quot;http://www.slideshare.net/nperriault/30-symfony-best-practices&quot; hreflang=&quot;en&quot;&gt;this is really bad&lt;/a&gt; &lt;img src=&quot;/blog/themes/battlestar/smilies/wink.gif&quot; alt=&quot;;)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries#rev-pnote-1123-2&quot; id=&quot;pnote-1123-2&quot;&gt;2&lt;/a&gt;] I&amp;#8217;m using Doctrine 1.2 beta (bundled with upcoming symfony 1.3) in the provided example.&lt;/p&gt;&lt;/div&gt;&lt;hr/&gt;&lt;p style=&quot;margin:.5em 0;padding:.5em;border:1px solid #333;background:#eee;color:#222&quot;&gt;&lt;small&gt;Ce billet intitulé &lt;a href=&quot;http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries&quot;&gt;Optimize your Doctrine Workflow with Specialized Queries&lt;/a&gt; a été rédigé par &lt;a href=&quot;http://prendreuncafe.com/cv&quot;&gt;Nicolas Perriault&lt;/a&gt; et publié sur le blog &lt;a href=&quot;http://prendreuncafe.com/blog/&quot;&gt;Prendre un Café&lt;/a&gt; sous licence &lt;a href=&quot;http://creativecommons.org/licenses/by-nc-sa/2.5/&quot;&gt;Creative Commons BY-NC-SA&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;</description>
    
    
    
      </item>
    
</channel>
</rss>

