<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WO Blog &#187; Symfony</title>
	<atom:link href="http://www.whiteoctober.co.uk/blog/tag/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.whiteoctober.co.uk/blog</link>
	<description>Great stuff about the web</description>
	<lastBuildDate>Thu, 09 May 2013 13:17:38 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4</generator>
		<item>
		<title>Sending emails in Silex via Swiftmailer spool</title>
		<link>http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 14:25:06 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Web technologies]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[Silex]]></category>
		<category><![CDATA[Swiftmailer]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=764</guid>
		<description><![CDATA[In Symfony2 it is relatively simple to send emails via a spool file, however in Silex we don&#8217;t have a console. So we&#8217;ll have to make one and it&#8217;s very simple. First you need to have the Symfony2 Console component setup in your Silex project. The following console file is based on the example in [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/"     class="crp_title">Functional testing sending emails in Silex</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/12/07/keeping-track-of-dom-manipulation/"     class="crp_title">Keeping track of Dom manipulation</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>In Symfony2 it is <a href="http://symfony.com/doc/current/cookbook/email/spool.html">relatively simple</a> to send emails via a spool file, however in <a href="http://silex-project.org/">Silex</a> we don&#8217;t have a console.</p>
<p>So we&#8217;ll have to make one and it&#8217;s very simple.</p>
<p>First you need to have the Symfony2 <a href="https://github.com/symfony/Console">Console component</a> setup in your Silex project.</p>
<p>The following console file is based on the example in <a href="http://beryllium.ca/?p=481">this blog</a> post and the Swiftmailer bundle console.</p>
<p><script src="https://gist.github.com/1125244.js?file=console.php"></script></p>
<p>Make that file executable, or remove the first line and call it through the php cli.</p>
<p>You will also have to do a little change to your current Silex bootstrap file:</p>
<p><script src="https://gist.github.com/1125244.js?file=bootstrap.php"></script></p>
<p>That should be it. This means you can now have a cron running to send emails and to the user they don&#8217;t have the wait while the SMTP server responds.</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/"     class="crp_title">Functional testing sending emails in Silex</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/12/07/keeping-track-of-dom-manipulation/"     class="crp_title">Keeping track of Dom manipulation</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Functional testing sending emails in Silex</title>
		<link>http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 11:29:03 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Silex]]></category>
		<category><![CDATA[Swiftmailer]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=760</guid>
		<description><![CDATA[We are slowly starting to fall in love with Silex the Micro Framework built using Symfony2 here at White October towers. Here is a quick code sample which shows how to test emails that are sent using Silex and Swiftmailer. I would recommend using this example app to get Silex and Swiftmailer setup if you [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/"     class="crp_title">Sending emails in Silex via Swiftmailer spool</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/12/07/keeping-track-of-dom-manipulation/"     class="crp_title">Keeping track of Dom manipulation</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>We are slowly starting to fall in love with <a href="http://silex-project.org/">Silex</a> the Micro Framework built using <a href="http://symfony.com/">Symfony2</a> here at White October towers.</p>
<p>Here is a quick code sample which shows how to test emails that are sent using Silex and Swiftmailer.</p>
<p>I would recommend using <a href="https://github.com/helios-ag/Silex-SwiftMailer-Email-Sending-Example">this example app</a> to get Silex and Swiftmailer setup if you haven&#8217;t got a working setup.</p>
<p>The aim in the code is to stop sending of real email in the test environment and log the messages so we can test them.</p>
<p>Here is a quick gist of the Test class, testing for number of emails sent and the first emails subject.</p>
<p><script src="https://gist.github.com/1117957.js?file=SwiftTest.php"></script></p>
<p>I have copied out the Symfony2 MessageLogger.php class from the SwiftmailerBundle, which I&#8217;ve included in the <a href="https://gist.github.com/1117957">gist</a> for your convenience. </p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/"     class="crp_title">Sending emails in Silex via Swiftmailer spool</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/12/07/keeping-track-of-dom-manipulation/"     class="crp_title">Keeping track of Dom manipulation</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to test UTF-8 email subject lines in Symfony</title>
		<link>http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 13:23:50 +0000</pubDate>
		<dc:creator>smotraghi</dc:creator>
				<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=691</guid>
		<description><![CDATA[One of our clients needs to send emails with UTF-8 subject lines. Swift Mailer, which Symfony uses, makes this easy to do, but writing functional tests for it is another story.<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/"     class="crp_title">Functional testing sending emails in Silex</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/"     class="crp_title">Sending emails in Silex via Swiftmailer spool</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/12/07/keeping-track-of-dom-manipulation/"     class="crp_title">Keeping track of Dom manipulation</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;">
<p>(crossposted from Sebastian&#8217;s <a href="http://blog.motraghi.us/2011/01/how-to-test-utf-8-email-subject-lines-in-symfony/">personal blog</a>)</p>
<p>One of our clients needs to send emails with UTF-8 subject lines. Swift Mailer, which Symfony uses, makes this easy to do, but writing functional tests for it is another story. The problem is that, if non-ASCII characters are present in the subject line, Swift Mailer encodes them as required by <a href="http://datatracker.ietf.org/doc/rfc2047/">RFC 2047</a> – for example, a string like &#8220;Transformación&#8221; turns into &#8220;=?utf-8?Q?Transformaci=C3=B3n?=&#8221;. How do we know that this is the right subject line?</p>
<p>There&#8217;s no immediately-available &#8220;convert this into a RFC 2047-compliant subject line&#8221; function, but we can get around this by making use of <code>Swift_Message-&gt;toString</code> and some choice preg functions.</p>
<p>First, create a dummy message containing the appropriate header. <code>Swift_Message-&gt;toString()</code> will contain our encoded header:</p>
<p><script src="https://gist.github.com/794680.js?file=gistfile1.php"></script> Next, we have to extract our encoded header – I&#8217;ve used <code>preg_match()</code> and a fairly simple regex.  <script src="https://gist.github.com/794680.js?file=gistfile2.php"></script></p>
<p>Finally, now that the encoded header has been extracted, we need only wrap it in <code>preg_quote()</code> (because <code>checkHeader()</code> uses regex syntax) and test away.</p>
<p><script src="https://gist.github.com/794680.js?file=gistfile3.php"></script></p>
<p>Voila – now we can be confident that our test script can deal with Unicode email subjects.</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/01/functional-testing-sending-emails-in-silex/"     class="crp_title">Functional testing sending emails in Silex</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/"     class="crp_title">Sending emails in Silex via Swiftmailer spool</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/12/07/keeping-track-of-dom-manipulation/"     class="crp_title">Keeping track of Dom manipulation</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stored functions with Symfony and Doctrine</title>
		<link>http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 09:17:12 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=665</guid>
		<description><![CDATA[A Symfony project I’m working on currently requires a couple of MySQL stored functions to be available. In the interests of making the code I write reusable in future, some of it has been moved into a plugin, but this code relies on a couple of stored functions being available.<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://www.symfony-project.org/">Symfony</a> project I&#8217;m working on currently requires a couple of <a href="http://www.mysql.com/">MySQL</a> stored functions to be available.  In the interests of making the code I write reusable in future, some of it has been moved into a plugin, but this code relies on a couple of stored functions being available.  As this code is also unit tested, I needed to make sure the stored functions were available on database drop-and-load which happens in the unit test bootstrap (via the <a href="http://www.doctrine-project.org/">Doctrine</a> tasks provided).</p>
<p>First of all, my stored functions are in separate .sql files in my plugin&#8217;s <code>data/sql/</code> directory in the interests of following convention within the project&#8217;s directory structure.</p>
<p>Secondly, in myPlugin/config/MyPluginConfiguration.class.php file, I have the following for the <code>initialize()</code> method.:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;zz_myplugin_dir&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRootDir</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dispatcher</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;command.post_command&quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'initializeStoredFuncs'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We listen for the <code>command.post_command</code> event which we can then check to see if it&#8217;s a Doctrine insert-sql task being run.  We also check to see if the function already exists before attempting to create it &#8211; if not, then carry on.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> initializeStoredFuncs<span style="color: #009900;">&#40;</span>sfEvent <span style="color: #000088;">$event</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  static <span style="color: #000088;">$doneConfig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$doneConfig</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Already done it.</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$event</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> instanceof sfDoctrineInsertSqlTask<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Not inserting any SQL. No point continuing</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Get database connection</span>
  <span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> Doctrine_Manager<span style="color: #339933;">::</span><span style="color: #004000;">connection</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Configure function 1</span>
  <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">addStoredRoutine</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;myFuncName1&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;myFuncName1.sql&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Configure function 2</span>
  <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">addStoredRoutine</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;someOtherFunc&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;someOtherFunc.sql&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Set config completed flag for later</span>
  <span style="color: #000088;">$doneConfig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Adds a stored procedure into the database
*
* @param string $con Connection to use
* @param string $routineName Routine name
* @param string $routineFile Filename inside our [plugin dir]/data/sql/
*/</span>
protected static <span style="color: #000000; font-weight: bold;">function</span> addStoredRoutine<span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routineName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routineFile</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$con</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOptions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$dsn</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;dsn&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/dbname=([^;]+)[;]?/&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$dsn</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$dbname</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT COUNT(*) AS c FROM information_schema.routines WHERE routine_name = '<span style="color: #006699; font-weight: bold;">{$routineName}</span>' AND routine_schema = '<span style="color: #006699; font-weight: bold;">{$dbname}</span>'&quot;</span><span style="color: #339933;">;</span>
  try
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$dbh</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$con</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDbh</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// No database available - can't carry on</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000088;">$resultSet</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$dbh</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$resultSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetch</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;c&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Create the function</span>
    <span style="color: #000088;">$sqlRoutine</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;zz_myplugin_dir&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;/data/sql/&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$routineFile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$con</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDbh</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sqlRoutine</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I&#8217;m not a massive fan of the way the database name has been retrieved but it works for now :-) I&#8217;m pretty sure there&#8217;s a neater way of accomplishing the above too, but this is working consistently and allows the stored functions to become part of a plugin, so that if the plugin is removed at a later date, then any subsequent database builds will not have unnecessary routines hanging around.</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony &#8211; file uploads with custom names and paths</title>
		<link>http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/#comments</comments>
		<pubDate>Thu, 07 Oct 2010 08:03:25 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[Web technologies]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=617</guid>
		<description><![CDATA[I&#8217;ve been experimenting and doing a bit of digging with the Symfony file uploading in forms functionality. Out of the box, with eg. a Doctrine model, Symfony will save the filename only of an uploaded file, and it usually generates a random filename consisting of a hash of the original name together with a random [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been experimenting and doing a bit of digging with the <a href="http://www.symfony-project.org">Symfony</a> file uploading in forms functionality.  Out of the box, with eg. a Doctrine model, Symfony will save the filename <strong>only</strong> of an uploaded file, and it usually generates a random filename consisting of a hash of the original name together with a random number, and then appending the extension to the end.  So your database entry ends up looking something like:</p>
<p><code>id:  1<br />
name: Joe Bloggs<br />
profile_picture: ffba81d3ac4ef1dcba70.txt</code></p>
<p>Great, if you&#8217;re not concerned about the appearance of the filename after uploading.  If however, you want to preserve the filename, then you can create a <code>generateFilename()</code> method in your form object and Symfony will use that. But, what if you want to store more than the filename in your database, for example part of a path including multiple levels deep in directories? Or you want to do this each time, but don&#8217;t want to have to recreate/copy the same method multiple times? Or both?! Enter the use of <code>sfValidatedFile</code>.</p>
<p>In my experimentation, I wanted a custom file upload path, something like this:</p>
<ul>
<li><code>/home/rich/myproject/web/uploads/entries/4cad77fd2da01/1/filename.txt</code></li>
<li><code>/home/rich/myproject/web/uploads/entries/4cad77fd2da01/2/otherfile.jpg</code></li>
</ul>
<p>but I wanted to be able to store everything from 4cad&#8230; onwards as the filename, as everything up to &#8216;entries&#8217; was a Symfony configuration value.</p>
<p>So, in your form <code>configure()</code> method, do something like the following:<br />
<code><br />
// Generate your unique path here<br />
$path = sfConfig::get("sf_my_upload_path") . DIRECTORY_SEPARATOR . uniqid();<br />
</code><code><br />
$this->validatorSchema["myFileUpload"] = new sfValidatorFile(array("path" => $thisPath, "validated_file_class" => "myValidatedFile");<br />
</code></p>
<p>This tells Symfony to use a custom path to save, but also to use the <code>myValidatedFile</code> class to handle the processing of the uploaded file &#8211; move it to the correct place and so on.  The <code>myValidatedFile</code> class is what we&#8217;re going to use to accomplish the above challenges.</p>
<p>Next, create the file <code>lib/vendor/myValidatedFile.class.php</code>:</p>
<p><code><br />
class myValidatedFile extends sfValidatedFile<br />
{<br />
&nbsp;&nbsp;public function generateFilename()<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return $this->path . DIRECTORY_SEPARATOR . $this->getOriginalName();<br />
&nbsp;&nbsp;}<br />
</code><code><br />
&nbsp;&nbsp;public function save($file = null, $fileMode = 0666, $create = true, $dirMode = 0777)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;$result = parent::save($file, $fileMode, $create, $dirMode);<br />
</code><code><br />
&nbsp;&nbsp;&nbsp;&nbsp;// Alter the savedName to reflect what we're after<br />
&nbsp;&nbsp;&nbsp;&nbsp;$this->savedName = str_replace(sfConfig::get("sf_my_upload_path") . DIRECTORY_SEPARATOR, "", $this->savedName);<br />
</code><code><br />
&nbsp;&nbsp;&nbsp;&nbsp;return null === $this->path ? $this->savedName : str_replace($this->path.DIRECTORY_SEPARATOR, '', $this->savedName);<br />
&nbsp;&nbsp;}<br />
}<br />
</code></p>
<p><a title="I cannot believe I am linking to this..." href="http://www.youtube.com/watch?v=4Ust9YBlEfY">Simples</a>. Let&#8217;s take each method in turn.</p>
<p>The first method simply returns the full path and original filename.  Symfony will use the directory of this when deciding where to save the file, and it will use the leaf part to determine the file&#8217;s name.  Part 1 accomplished!</p>
<p>The second method calls the original sfValidatedFile <code>save()</code> method. We&#8217;re not concerned with the mechanics of saving the file, so we&#8217;ll just do as normal (we&#8217;ve already set the path above).  What we are concerned with is creating the correct value to be saved into the database or whatever you do with the field value eventually.</p>
<p>The key parts are the final 2 lines.  Essentially here, we remove the part of the file&#8217;s path and filename that we have stored in the configuration value.  This means that what is left will be (in the example above), our <code>uniqid()</code> value and the filename.  This return value is what is saved/used elsewhere.</p>
<p>And then, your database entry will look like this:</p>
<p><code>id:  1<br />
name: Joe Bloggs<br />
profile_picture: 4cad77fd2da01/2/joes_picture.jpg<br />
</code></p>
<p>All you need to do now is set the &#8220;validated_file_class&#8221; option value on your file upload widget to <code>myValidatedFile</code> whenever you need this functionality, and job done!</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A stack of twits</title>
		<link>http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/#comments</comments>
		<pubDate>Tue, 29 Jun 2010 12:57:29 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Web technologies]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=566</guid>
		<description><![CDATA[Here at White October towers we pride ourselves on not knowing everything. This is what the internet was made for. So when we are stumped on a problem we hit the Google. These days however our first point of call for any technical programming problems is Stack Overflow. A quick search of that site usually [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/"     class="crp_title">JavaScript Inheritance done right</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/06/13/blackberry-jam-10-blackberry-world/"     class="crp_title">Blackberry Jam 10 &#038; Blackberry World</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/03/03/wocowork-our-first-year-of-coworking/"     class="crp_title">wocowork – Our first year of Coworking</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/11/22/barcamp-not-for-profit-oxford/"     class="crp_title">Barcamp Not For Profit Oxford</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/09/14/mailchimp-user-interface-testing/"     class="crp_title">MailChimp user interface testing</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>Here at White October towers we pride ourselves on not knowing everything. This is what the internet was made for. So when we are stumped on a problem we hit the <a href="http://google.co.uk">Google</a>. These days however our first point of call for any technical programming problems is <a href="http://stackoverflow.com/">Stack Overflow</a>. A quick search of that site usually turns up someone else with a similar problem and if we are very lucky someone has posted up a solution. If not we post up a question and people will try their best to post an answer.</p>
<p>As we find it a good resource we try and answer questions on things we know about, in turn for answers you get points and sometimes badges.  The badges/points side of things is a little childish but very addictive and a more productive use of time than <a href="http://youtube.com">Youtube</a>.</p>
<p>Recently <a href="http://blog.stackoverflow.com/2010/05/stack-exchange-api-public-beta-starts/">Stack Overflow released an API</a> and I thought that joining Stack Overflow and <a href="http://twitter.com">Twitter</a> together sounded like a fun reason to play with both websites&#8217; APIs.</p>
<p>So <a href="http://stackoftwits.com">Stack of Twits</a> was born and <a href="http://stackapps.com/questions/924/a-stack-of-twits-tweeting-all-over-your-stack">unleashed to the world last night</a>. Simply it sends you a message on <a href="http://twitter.com/">Twitter</a> when a question matches your set of  keywords.</p>
<p><a href="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/06/screen_shot.png"><img class="aligncenter size-medium wp-image-571" title="screen_shot" src="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/06/screen_shot-300x183.png" alt="" width="300" height="183" /></a></p>
<p>I built the site using our framework of choice <a href="http://www.symfony-project.org/">symfony</a> very quickly. It only took me a few hours over the course of a week or so to get it together. While building it I have made a PHP wrapper for the Stack Overflow API and the plan is to open source this work. Any interest in it pre release please comment below.</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/"     class="crp_title">JavaScript Inheritance done right</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/06/13/blackberry-jam-10-blackberry-world/"     class="crp_title">Blackberry Jam 10 &#038; Blackberry World</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/03/03/wocowork-our-first-year-of-coworking/"     class="crp_title">wocowork – Our first year of Coworking</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/11/22/barcamp-not-for-profit-oxford/"     class="crp_title">Barcamp Not For Profit Oxford</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/09/14/mailchimp-user-interface-testing/"     class="crp_title">MailChimp user interface testing</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Symfony admin generator theming</title>
		<link>http://www.whiteoctober.co.uk/blog/2010/03/23/symfony-admin-generator-theming/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2010/03/23/symfony-admin-generator-theming/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 13:04:33 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=502</guid>
		<description><![CDATA[From this&#8230; To this (at the click of a few generator.yml changes)! As part of one of our current Symfony projects in work, a colleague and I decided that rather than reinventing the wheel everytime we used a new admin-generated module in the application with regards to overriding partials and actions in pretty much the [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>From this&#8230;<br />
<a href="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/03/old-edit-user.jpg"><img class="alignleft size-medium wp-image-515" title="old-edit-user" src="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/03/old-edit-user-300x154.jpg" alt="old-edit-user" width="300" height="154" /></a><br />
To this (at the click of a few <code>generator.yml</code> changes)!<br />
<a href="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/03/new-edit-user.jpg"><img class="alignleft size-medium wp-image-516" title="new-edit-user" src="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/03/new-edit-user-300x179.jpg" alt="new-edit-user" width="300" height="179" /></a></p>
<p>As part of one of our current <a href="http://www.symfony-project.org/">Symfony</a> projects in work, a colleague and I decided that rather than reinventing the wheel everytime we used a new <a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/12">admin-generated module</a> in the application with regards to overriding partials and actions in pretty much the same way each time, it would be productive and easier in the long run to create an admin generator theme.  The documentation on the Symfony site for this is sparse to say the least, and when I get some time, I&#8217;ll look at contributing back to the Symfony docs a condensed version of this blog post so that it’s a bit more straightforward for the next person.  You have the ability to customise pretty much every part of the admin generator including batch actions, form actions, filters, table headers and so on, so it&#8217;s worth the work in the long run if you&#8217;re looking for quick admin-generated module deployments in line with your site&#8217;s template.</p>
<p>OK, so before I start, be warned this is nice and long (and hopefully explanatory)&#8230;!  I&#8217;ll also say that <strong>clearing your cache</strong> upon making changes to partials is <strong>vital</strong>.  I repeat, <strong>VITAL</strong>! :-)</p>
<h2>Getting started</h2>
<p>The first step I carried out, which is mentioned on the Symfony site, was to copy all the files from the default theme into your project.  In our case, we&#8217;re using <a href="http://www.doctrine-project.org/">Doctrine</a> as the ORM, so the files were found in <code>lib/vendor/symfony/plugins/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin</code>, and they were copied to <code>data/generator/sfDoctrineModule/ourTheme</code>.  This directory contains 3 subdirectories – we&#8217;ll need all 3.  The names should be self-explanatory &#8211; &#8220;<code>parts</code>&#8221; consists of all the parts needed to dynamically generate the code, &#8220;<code>skeleton</code>&#8221; consists of skeleton files that form the basis of the final module (<code>generator.yml</code> etc), and &#8220;<code>template</code>&#8221; consists of the template files that use the files in &#8220;<code>parts</code>&#8220;. Simple!</p>
<p>That&#8217;s the basic step out of the way.  If you want to check that everything is being correctly read here, simply alter an existing generator.yml file as follows:</p>
<p><code>theme:    ourTheme</code></p>
<p><strong>Clear your cache</strong>, and reload your page.  You shouldn&#8217;t see any change – this is because the files are exactly the same as the default theme.  Now comes the fun part!</p>
<p>For the following paths, I&#8217;ll assume the prefix of <code>data/generator/sfDoctrineModule/ourTheme/</code> to avoid typing it out each time.</p>
<h2>Adding configuration options</h2>
<p>The first change I wanted to carry out was to add some extra configuration options via the <code>generator.yml</code> file.  One major gripe I have with the Symfony admin generator is that once you&#8217;ve added a new object, or edited one, the default destination is the edit page, rather than the list page.  Personally I see returning to the list as expected behaviour, and every project I use the admin generator in, I end up overriding the <code>processForm()</code> action and making this change.  I wanted to be able to specify this destination via a configuration option on the &#8216;new&#8217; and &#8216;edit&#8217; contexts, with a &#8216;return_to&#8217; option.  Carrying out this change involves overriding some other classes in Symfony, most notably the <code>sfModelGeneratorConfiguration</code> class.  I copied this class from the Symfony core to <code>lib/generator/myModelGeneratorConfiguration.class.php</code>.</p>
<p>Once you&#8217;ve done this, alter <code>parts/configuration.php</code> so that the generated class extends from <code>myModelGeneratorConfiguration</code> instead of <code>sfModelGeneratorConfiguration</code>.</p>
<p>Open up this class, and you&#8217;ll see a lot of abstract methods defined near the top.  These methods are created during the generation process, and are located in the <code>parts/fieldsConfiguration.php</code> file.  You&#8217;ll see that it consists of what looks like PHP within PHP – this is a common theme throughout the development of an admin generator theme, and can get a tad confusing if you forget what context you&#8217;re in when you&#8217;re writing code!  You can use the example methods to build your own.  In my case, I added the following:</p>
<p><code>public function getNewReturnTo()<br />
{<br />
return '&lt;?php echo $this-&gt;escapeString(isset($this-&gt;config['new']['return_to']) ? $this-&gt;config['new']['return_to'] : 'edit') ?&gt;';<br />
&lt;?php unset($this-&gt;config['new']['return_to']) ?&gt;<br />
}</code><br />
<code><br />
public function getEditReturnTo()<br />
{<br />
return '&lt;?php echo $this-&gt;escapeString(isset($this-&gt;config['edit']['return_to']) ? $this-&gt;config['edit']['return_to'] : 'edit') ?&gt;';<br />
&lt;php unset($this-&amp;gtconfig['edit']['return_to']) ?&gt;<br />
}<br />
</code><br />
These methods both return a configuration value if it exists in the YAML file, or the defaults of &#8216;new&#8217; and &#8216;edit&#8217; respectively if no configuration value is specified.</p>
<p>In order to make this option available in the configuration, the <code>myModelGeneratorConfiguration-&gt;compile()</code> method should be altered to allow this option:</p>
<p><code>// ...<br />
'new'    =&gt; array(<br />
'fields'  =&gt; array(),<br />
'title'   =&gt; $this-&gt;getNewTitle(),<br />
'actions' =&gt; $this-&gt;getNewActions() ? $this-&gt;getNewActions() : $this-&gt;getFormActions(),<br />
'return_to' =&gt; $this-&gt;getNewReturnTo()<br />
),<br />
// …<br />
</code></p>
<p>and the same for the edit option.  The final change is to actually action this change in the <code>processForm()</code> method, conveniently found in <code>parts/processFormAction.php</code>.  This file (along with all the other <code>*Action.php</code> files) are included in the generated <code>sfActions</code> class specific to the module you&#8217;re creating.  I removed the final redirect line which redirected back to the &#8216;edit&#8217; URL, and replaced it with the following changes:</p>
<p><code>// ...<br />
if ($form-&gt;isValid())<br />
{<br />
$thisContext = $form-&gt;getObject()-&gt;isNew() ? 'new' : 'edit';<br />
$notice = $form-&gt;getObject()-&gt;isNew() ? 'The item was created successfully.' : 'The item was updated successfully.';</code><br />
<code><br />
// ...<br />
$this-&gt;redirect('@&lt;?php echo $this-&gt;getUrlForAction('new') ?&gt;');<br />
}<br />
else<br />
{<br />
$route = '&lt;?php echo $this-&gt;getSingularName(); ?&gt;';<br />
$returnTo = strtolower($this-&gt;configuration-&gt;getValue($thisContext . '.return_to'));<br />
if ($returnTo != 'list')<br />
{<br />
$route .= '_' . $returnTo;<br />
}</code><br />
<code><br />
$returnArray = array('sf_route' =&gt; $route);<br />
if ($returnTo != 'list')<br />
{<br />
$returnArray['sf_subject'] = $&lt;?php echo $this-&gt;getSingularName(); ?&gt;;<br />
}<br />
$this-&gt;redirect($returnArray);<br />
</code></p>
<p>That&#8217;s it! Add the configuration option into your generator.yml as follows:<br />
<code>new:<br />
return_to: list<br />
</code></p>
<p><strong>Clear your cache</strong>, reload the page and test it out.  After creating a new object, you should be returned to the list.  This is restricted to eg <code>my_model_ACTION</code>-type routes, but you can easily enhance the above code to redirect to any other route, check for an &#8220;@&#8221; symbol if needs be and so on.</p>
<h2>New &#8220;contexts&#8221;</h2>
<p>I wanted to implement an Ajax edit form on a &#8220;view&#8221; page for my model, so that the user wasn’t taken away.  The templates I was working from had this as a pop-over box, but instead of redirecting the user afterwards, I wanted the edit and update to be seamless.  In terms of the form, the ajax form was similar (but slightly different) to the normal admin-generated edit form, so I wanted the ability to be able to configure the form separately from the edit page.</p>
<p>I experimented with configuring it as part of my &#8216;view&#8217; context but ran into problems with nested array configurations, so I decided to abstract it out and create a new &#8220;context&#8221; with which I could configure items in the same way as a normal context (&#8216;new&#8217;, &#8216;edit&#8217;, &#8216;list&#8217; and so on).  I termed this &#8216;ajaxedit&#8217;;  NB I’m calling them &#8216;contexts&#8217; here as I’m sure I read that’s what they were called somewhere! Correct me if not ;-)</p>
<p>The creation of this is very similar to the above changes for adding a configuration value.  In <code>myModelGeneratorConfiguration.class.php</code>, add the following in to the configuration array in <code>compile()</code>:</p>
<p><code>'ajaxedit' =&gt; array(<br />
'title'   =&gt; $this-&gt;getAjaxeditTitle(),<br />
'actions' =&gt; $this-&gt;getAjaxeditActions() ? $this-&gt;getAjaxeditActions() : $this-&gt;getFormActions(),<br />
'fields'  =&gt; array()<br />
</code></p>
<p>I added this after the &#8216;edit&#8217; one currently there.  If you proceed down through this method, I also duplicated the &#8216;edit&#8217; line in the first <code>foreach()</code> loop, where the fields are configured using <code>sfModelGeneratorConfigurationField</code>, and altered &#8216;edit&#8217; to &#8216;ajaxedit&#8217; where appropriate.  Same in the &#8216;virtual fields&#8217; configuration, the form actions, the field configuration (duplicated from &#8216;list field configuration&#8217;), and the <code>$this-&gt;parseVariables()</code> lines.</p>
<p>You should also add &#8216;ajaxedit&#8217; to the credentials array near the end of the <code>compile()</code> method, so that you can control access to the popup/context with credentials, and again into the <code>getConfig()</code> method at the end of the class.</p>
<p>You then need to create the relevant abstract methods as before, so that the context can be correctly configured.  Again, I used the &#8216;edit&#8217; context as an example to base my changes and additions on.</p>
<p>The next step is to configure the templates and partials so that they recognise this.  I used the default <code>_form.php</code> partial so that I could re-use code where possible, but added a &#8216;context&#8217; variable to the partial when calling it, eg. in my view page:</p>
<p><code><br />
[?php include_partial('&lt;?php echo $this-&gt;getModuleName() ?&gt;/form', array('&lt;?php echo $this-&gt;getSingularName() ?&gt;' =&gt; $&lt;?php echo $this-&gt;getSingularName() ?&gt;, 'form' =&gt; $form, 'configuration' =&gt; $configuration, 'helper' =&gt; $helper, 'context' =&gt; 'ajaxedit')) ?]<br />
</code></p>
<p>In my form partial, I then altered the <code>getFormFields()</code> call to the following:</p>
<p><code><br />
[?php foreach ($configuration-&gt;getFormFields($form, $form-&gt;isNew() ? 'new' : 'edit') as $fieldset =&gt; $fields): ?]<br />
</code></p>
<p>so that I was using the correct set of fields for the form display.  Don&#8217;t forget to <strong>clear your cache</strong> after making these changes.</p>
<p>You can handle the ajax post however you like; I used <a href="http://jquery.com/">jQuery</a> and a callback handler to adjust details and display new values etc where required.  The handling of the form data was done in the same way as a normal Symfony action; details of this (and Ajax-specific stuff) are in the main Symfony documentation.</p>
<p>Here&#8217;s the result:<br />
<a href="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/03/ajax-edit.jpg"><img class="alignleft size-medium wp-image-522" title="ajax-edit" src="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/03/ajax-edit-300x196.jpg" alt="ajax-edit" width="300" height="196" /></a></p>
<h2>Conclusion</h2>
<p>The one major thing to remember is that <strong>clearing your cache</strong> is <strong>VITAL</strong> to a speedy admin generator theme development.  If you&#8217;re running in dev mode via your front controller, then Symfony will only regenerate partials that are directly related to your <code>generator.yml</code> on the fly.  It won&#8217;t recreate action templates if there is no need to from <code>generator.yml</code> changes.  This means that you will need to manually call &#8220;<code>./symfony cc</code>&#8221; from the command line whenever you make changes to partials.  I lost count of how many times I ran that task during my theme development :-)</p>
<p>I&#8217;d imagine there are nicer ways to do some of the above – I&#8217;m not particularly a fan of the overriding of classes and having them separate from the theme, although I know that Symfony&#8217;s autoloading can be pretty clever sometimes, so it would probably find the classes with a bit of tweaking, if I put them as part of the theme.  It&#8217;s also a bit tricky to get your head around the whole PHP-creating-PHP idea, and remembering whereabouts you are, and what variables you have available to you.  I lost a good few hours trying to use variables that were in the top-level PHP, in my generated partials, and wondering why they weren’t working.</p>
<p>However, the end result is definitely worth it and saves a lot of time in the long run if you&#8217;re looking to re-use templates and code across a number of admin-generated modules!</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2010/03/23/symfony-admin-generator-theming/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Hudson and Symfony continuous integration</title>
		<link>http://www.whiteoctober.co.uk/blog/2010/02/05/hudson-and-symfony-continuous-integration/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2010/02/05/hudson-and-symfony-continuous-integration/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 15:02:34 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=460</guid>
		<description><![CDATA[We&#8217;ve been experimenting this week with using Hudson as our continuous integration server for our latest Symfony project.  Previous experiences with CruiseControl via phpUnderControl and the symfonyUnderControl plugin were OK-ish but we&#8217;d occasionally experience CruiseControl dying on us with no warning apart from the lack of emails after checking our code in. So we decided [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/"     class="crp_title">Sending emails in Silex via Swiftmailer spool</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/"     class="crp_title">A stack of twits</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve been experimenting this week with using <a title="Hudson" href="http://hudson-ci.org/">Hudson</a> as our continuous integration server for our latest <a href="http://www.symfony-project.org/">Symfony</a> project.  Previous experiences with <a title="CruiseControl" href="http://cruisecontrol.sourceforge.net/">CruiseControl</a> via <a title="phpUnderControl" href="http://phpundercontrol.org/">phpUnderControl</a> and the <a title="symfonyUnderControl" href="http://www.symfony-project.org/plugins/symfonyUnderControlPlugin">symfonyUnderControl</a> plugin were OK-ish but we&#8217;d occasionally experience CruiseControl dying on us with no warning apart from the lack of emails after checking our code in.</p>
<p>So we decided it was time to perhaps investigate alternatives.  The obvious choice for Symfony would be to use <a title="Sismo" href="http://ci.symfony-project.org/">Sismo</a>, but sadly it hasn&#8217;t been released yet&#8230; <a title="Fabien Potencier" href="http://fabien.potencier.org">Fabien</a>, any clues as to a release date? ;-) It looks at the moment as if we&#8217;re stuck with a Java-based solution, so we decided to look at Hudson as an alternative.</p>
<p>Setting up Hudson was straightforward using <a title="Hudson and Symfony by Nicolas Perriault" href="http://prendreuncafe.com/blog/post/2009/10/06/Simple-Continuous-Integration-of-a-Symfony-Project-using-Hudson">Nicolas Perriault&#8217;s blog post</a> on exactly what we were trying to achieve, linking in with our Subversion repository.  The configuration of the projects took a bit of faffing &#8211; for some reason, Hudson liked to check out the whole repository rather than just eg the trunk folder  as specified, so this screwed up some of the paths.  A bit of trial and error later and we were up and running with a build every 30mins if there are new commits, as this pretty graph shows&#8230; (using the jUnit XML output available in Symfony 1.4).  Total number of tests in blue, failures in red.</p>
<p><img class="alignleft size-medium wp-image-461" title="Hudson build trend output" src="http://www.whiteoctober.co.uk/blog/wp-content/uploads/2010/02/build-trend-300x120.png" alt="Hudson build trend output" width="300" height="120" /></p>
<p>One thing to bear in mind if you&#8217;re getting test failures randomly, or perhaps always after a certain developer checks in (and it&#8217;s not a result of broken code) is to ensure that the permissions are correct for Symfony, as SVN likes to store permissions where it can.  The fix for this, apart from committing new permissions, is to add a build step in Hudson that carries out ./symfony project:permissions (Symfony 1.3+) shortly before the build.  This seems to solve it nicely, and explained the small red peaks in the graph above.</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/08/04/sending-emails-in-silex-via-swiftmailer-spool/"     class="crp_title">Sending emails in Silex via Swiftmailer spool</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/"     class="crp_title">A stack of twits</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/25/how-to-test-utf-8-email-subject-lines-in-symfony/"     class="crp_title">How to test UTF-8 email subject lines in Symfony</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2010/02/05/hudson-and-symfony-continuous-integration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t be afraid to NOT use the ORM&#8230;</title>
		<link>http://www.whiteoctober.co.uk/blog/2009/10/16/dont-be-afraid-to-not-use-the-or/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2009/10/16/dont-be-afraid-to-not-use-the-or/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 15:06:03 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[Web technologies]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=353</guid>
		<description><![CDATA[I&#8217;ve been racking my brains the past couple of days with a Doctrine issue within a Symfony project. I was constructing a bank statement-esque page, which iterated over a &#8220;StatementEntry&#8221; table and displayed the results. Entries could either be of model Type A or model Type B, with the relevant model ID stored in the [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/"     class="crp_title">JavaScript Inheritance done right</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been racking my brains the past couple of days with a <a title="Doctrine" href="http://www.doctrine-project.org/">Doctrine</a> issue within a <a title="Symfony" href="http://www.symfony-project.org/">Symfony</a> project.  I was constructing a bank statement-esque page, which iterated over a &#8220;StatementEntry&#8221; table and displayed the results.  Entries could either be of model Type A or model Type B, with the relevant model ID stored in the StatementEntry table.  The relationship was defined by a &#8220;type&#8221; column.  Type A and B models also had other relationships after the initial one.</p>
<p>The problem I discovered was that obviously Doctrine didn&#8217;t know what the conditional relationships were, since it was dependant on the type column.  I researched some different approaches:</p>
<ol>
<li> <strong>Doctrine&#8217;s RawSql</strong>
<p>This approach worked for generating the correct SQL query without a problem, but the issue then arose of how Doctrine could hydrate the result set.  Answer was &#8211; it couldn&#8217;t :-) Well, I lie &#8211; I could use Doctrine::HYDRATE_SCALAR but I had issues with other related models, where I was joining to a table twice but under different aliases, which failed, since the scalar hydration would override earlier joins on the same table.</li>
<li> <strong>Column aggregation</strong>
<p>Column aggregation looked great initially &#8211; I could have a &#8220;TypeAEntry&#8221; and a &#8220;TypeBEntry&#8221;, and Doctrine would have handled the typing of the Entry automatically.  I couldn&#8217;t however see a way to query &#8220;in reverse&#8221; &#8211; get all Entries and their associated models.</li>
<li> <strong>Write a raw SQL query, and use Doctrine&#8217;s PDO instance to retrieve the data.</strong></li>
</ol>
<p>Option 3) was the one I settled for in the end.  It meant of course that I had to specify column names, and perform all the joins myself, but it did mean I could specify precisely what data I wanted back.  This came back in the form of a normal array.  I&#8217;d tried to stay away from this option intially, but after spending too long researching the other 2 and hitting brick walls, I bit the bullet and dropped down to the raw stuff.  And hey presto!</p>
<p>Note &#8211; this approach will only work if you want the data to be read-only.  If you want to then use Doctrine&#8217;s model goodness, you&#8217;ll need to work out how to transform that *back* into a model.</p>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2012/09/12/behat-tablenodes-the-missing-manual/"     class="crp_title">Behat TableNodes &#8211; the missing manual</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/"     class="crp_title">JavaScript Inheritance done right</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2009/10/16/dont-be-afraid-to-not-use-the-or/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Why I hate Criteria&#8221;</title>
		<link>http://www.whiteoctober.co.uk/blog/2008/10/08/why-i-hate-criteria/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2008/10/08/why-i-hate-criteria/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 12:46:06 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[Object-relational mapping]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=153</guid>
		<description><![CDATA[Nicking the title from the previous post, oh and the sentiment. I don&#8217;t hate Criteria**, it is actually quite good, however watching the video in the previous post reminded me of a few issues we have had in the office where we have complained about it or just got plain confused&#8230; I know Dan, for [...]<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/"     class="crp_title">A stack of twits</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li></ul></div>]]></description>
			<content:encoded><![CDATA[<p>Nicking the title from the <a href="http://www.whiteoctober.co.uk/blog/2008/10/07/why-i-hate-django/">previous post</a>, oh and the sentiment.  I don&#8217;t hate <a href="http://propel.phpdb.org/trac/wiki/Users/Documentation/1.3/Criteria">Criteria</a>**, it is actually quite good, however watching the video in the previous post reminded me of a few issues we have had in the office where we have complained about it or just got plain confused&#8230;</p>
<p>I know <a href="http://www.whiteoctober.co.uk/meet-the-staff-_27.html#dan">Dan</a>, for example, doesn&#8217;t see the point of using Criteria because what is wrong with SQL?</p>
<p>I have sat and scratched my head a few times trying to figure out how to query using Criteria, I know how I would do it in SQL but I can sit for ages trying to bend Criteria to my will.</p>
<p>I really should have <a href="http://propel.phpdb.org/trac/wiki/Users/Documentation/1.3/Criteria">RTFM</a>&#8230;</p>
<p style="padding-left: 30px;"><em>We do still recommend that you use SQL when it proves to be simpler, though.</em></p>
<p>Criteria is great when it fits your needs, but when it doesn&#8217;t or becomes very complex..stop step back and use SQL.</p>
<p>Using <a href="http://propel.phpdb.org/trac/">Propel 1.3</a> you get to use <a href="http://uk.php.net/manual/en/intro.pdo.php">PDO</a> and that is not something that is framework specific it&#8217;s an inbuilt <a href="http://www.php.net">PHP</a> database abstraction layer. So the skills you learn using PDO are transferable to another project that doesn&#8217;t use a framework but uses a database.</p>
<p>So we have a custom query that we want to run and get back a bunch of user objects and we really don&#8217;t want to use Criteria&#8230;easy:</p>
<p style="padding-left: 30px;">$name = &#8220;Wards&#8221;;<em><br />
</em>$bunchofusers = array();<em><br />
//Our highly complex query&#8230;.<br />
//Fancy prepared stuff you get from PDO&#8230;think sprintf<br />
</em>$stmt = $con-&gt;prepare(&#8220;SELECT * FROM user WHERE last_name = ?&#8221;);<br />
$stmt-&gt;bindValue(1, $name);<em><br />
//erm execute&#8230;<br />
</em>$stmt-&gt;execute();<em><br />
//Loop on our rows&#8230;and lets make some User objects..<br />
</em>while($row = $stmt-&gt;fetch()) {<br />
$oUser = new User();<br />
$oUser-&gt;hydrate($row);<br />
$bunchofusers[]=$oUser;<br />
}</p>
<p>Nothing really new to learn in the above code, it&#8217;s more like remembering that we can code how we choose too and we don&#8217;t have to be shackled to a certain way or slowed down by a framework when things don&#8217;t exactly fit.</p>
<p>** <em>&#8220;What is Criteria?&#8221; I hear you say&#8230;well it comes with the Propel ORM, and it is for building up queries using objects rather than SQL. We use Propel within the <a href="http://www.symfony-project.org/">symfony framework</a> as our current ORM of choice.</em></p>
<div class="zemanta-pixie"><a class="zemanta-pixie-a" title="Zemified by Zemanta" href="http://reblog.zemanta.com/zemified/a771d9f4-e213-47b4-b5f8-cafd6ee09603/"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_c.png?x-id=a771d9f4-e213-47b4-b5f8-cafd6ee09603" alt="Reblog this post [with Zemanta]" /></a></div>
<div class="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/"     class="crp_title">Getting into Behat with Symfony2</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/01/05/stored-functions-with-symfony-and-doctrine/"     class="crp_title">Stored functions with Symfony and Doctrine</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/"     class="crp_title">Symfony2 data collectors</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/06/29/a-stack-of-twits/"     class="crp_title">A stack of twits</a></li><li><a href="http://www.whiteoctober.co.uk/blog/2010/10/07/symfony-file-uploads-with-custom-names-and-paths/"     class="crp_title">Symfony &#8211; file uploads with custom names and paths</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2008/10/08/why-i-hate-criteria/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
