<?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>woblog &#187; Web development</title>
	<atom:link href="http://www.whiteoctober.co.uk/blog/category/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.whiteoctober.co.uk/blog</link>
	<description>great stuff about the web</description>
	<lastBuildDate>Mon, 05 Dec 2011 16:53:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Symfony2 data collectors</title>
		<link>http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 16:35:48 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Web technologies]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=792</guid>
		<description><![CDATA[I spent some time last week working on automated MailChimp integration with one of our Symfony2 sites. The project uses Behat and Mink extensively for BDD testing, so I wanted to be able to test that when users registered on our site, they were automatically added to the client&#8217;s MailChimp distribution list. Unsubscription could happen [...]]]></description>
			<content:encoded><![CDATA[<p>I spent some time last week working on automated <a href="http://www.mailchimp.com/" title="MailChimp">MailChimp</a> integration with one of our <a href="http://symfony.com" title="Symfony">Symfony2</a> sites.  The project uses <a href="http://behat.org/">Behat</a> and <a href="http://mink.behat.org/" title="Mink">Mink</a> extensively for BDD testing, so I wanted to be able to test that when users registered on our site, they were automatically added to the client&#8217;s MailChimp distribution list.  Unsubscription could happen via a checkbox in the user&#8217;s account settings and this needed to work the same way behind the scenes.</p>
<p>I opted to use one of the <a href="https://github.com/jirafe/MailChimpBundle">available MailChimp bundles</a> to aid integration and with a bit of tweaking this worked great.  The bundle comes with a stub connection which is able to collate requests sent and make them available for inspection.  I wanted to be able to utilise this neatly inside a set of tests, and potentially also make it available in the dev environment.  A bit of skimming the Symfony2 cookbook led me to the entry on <a href="http://symfony.com/doc/current/cookbook/profiler/data_collector.html">Symfony2 data collectors</a>.</p>
<p>The concept is simple &#8211; a data collector is registered and is able to, well, collect data!  For example, the number of queries during a request, or the number of emails sent.  This can then be accessed via the profiler in the relevant environment (dev, test etc).  In my case I wanted to collect and subsequently inspect all requests sent to MailChimp.</p>
<p>First step &#8211; create me a data collector:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">namespace</span> Jirafe\Bundle\MailChimpBundle\DataCollector<span style="color: #339933;">;</span>
&nbsp;
use Symfony\Component\HttpKernel\DataCollector\DataCollector<span style="color: #339933;">;</span>
use Symfony\Component\HttpFoundation\Request<span style="color: #339933;">;</span>
use Symfony\Component\HttpFoundation\Response<span style="color: #339933;">;</span>
use Jirafe\Bundle\MailChimpBundle\Connection\ConnectionInterface<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> MailChimpDataCollector <span style="color: #000000; font-weight: bold;">extends</span> DataCollector
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$connection</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>ConnectionInterface <span style="color: #000088;">$connection</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connection</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$connection</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> collect<span style="color: #009900;">&#40;</span>Request <span style="color: #000088;">$request</span><span style="color: #339933;">,</span> Response <span style="color: #000088;">$response</span><span style="color: #339933;">,</span> \Exception <span style="color: #000088;">$exception</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'requests'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequests</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRequestCount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'requests'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRequests<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'requests'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'mail_chimp'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The <code>collect()</code> method is the interesting part here &#8211; this is called whenever data collection is required &#8211; usually once per request.  We collect the requests from the connection supplied to the constructor.</p>
<p>Next step, register this during the bundle&#8217;s <code>load()</code> method:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Add connection to data collector</span>
<span style="color: #000088;">$definition</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDefinition</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mail_chimp.data_collector'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$definition</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addArgument</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Reference<span style="color: #009900;">&#40;</span><span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mail_chimp.connection.%s'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'connection'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The above uses the connection type specified in the bundle&#8217;s configuration option and previously registered as a service in the same method.  If you&#8217;re creating your own custom collector, this is just the normal parameters you&#8217;d pass in to your service when it&#8217;s instantiated.</p>
<p>Finally, I added a method and subsequent implementation to the interface and related connection classes within the bundle, so that MailChimp request objects were collected in an array, and made available to the data collector upon request. This is the <code>getRequests()</code> method listed above in the data collector; called in the <code>collect()</code> method. Quick &#8216;n&#8217; dirty here, since there would only ever be a single MailChimp request (possibly 2) made in any one request.</p>
<p>Once all this was in place, I could then test correctly.  Note that I&#8217;d rather have done the other way round (test and then develop) but since this was experimentation, I figured it was OK ;-) In my Behat scenarios, I added the <code>getSymfonyProfiler()</code> method detailed in a Behat/Mink <a href="http://docs.behat.org/cookbook/using_the_profiler_with_minkbundle.html">cookbook entry</a>, and proceeded to write my step (Behat 1.x-style):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Then</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^my email address is unsubscribed from the relevant MailChimp list$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$profiler</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSymfonyProfiler</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: #339933;">!</span><span style="color: #000088;">$profiler</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      throw <span style="color: #000000; font-weight: bold;">new</span> \RuntimeException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Symfony2 profiler not present for tests, wrong driver?&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$mcDataCollector</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$profiler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCollector</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;mail_chimp&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$listID</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;mailchimp_list_id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Check the requests made to make sure we have an unsubscribe</span>
    assertEquals<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mcDataCollector</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequestCount</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$requests</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mcDataCollector</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequests</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$req1</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$requests</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;listUnsubscribe&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$req1</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$req1</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParams</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    assertEquals<span style="color: #009900;">&#40;</span><span style="color: #000088;">$listID</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Fire the redirect on the client</span>
    <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDriver</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">followRedirect</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;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The final line here is as a result of disabling redirects in a previous step since the data collector operates on a per-request basis.  If you&#8217;re subscribing eg via a form POST, then you&#8217;ll need to disable redirects prior to submitting the form, otherwise your data collector will be empty when you check it.  Disable them and then redirect after you&#8217;ve carried out your checks.</p>
<p>The implementation for the above is up on our Github MailChimpBundle fork <a href="https://github.com/whiteoctober/MailChimpBundle">here</a>; I&#8217;m not particularly fond of having to hack about the connection classes, and ideally it would be nice to layer the data collector on top without having to adjust existing code. That said, it does the job fine here, and it&#8217;s good to use even more features of Symfony2 ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2011/12/05/symfony2-data-collectors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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 [...]]]></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>
]]></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 [...]]]></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>
]]></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>Getting into Behat with Symfony2</title>
		<link>http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 07:47:21 +0000</pubDate>
		<dc:creator>Rich</dc:creator>
				<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[Uncategorised]]></category>
		<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=740</guid>
		<description><![CDATA[I&#8217;ve spent the past week starting a new sprint on our latest large project, and as we&#8217;re keen to get our clients as involved as possible during sprints, we decided to get down with some Behaviour-Driven Development (BDD) which allows them to contribute to writing the actual acceptance criteria for the user stories. We&#8217;re pretty [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve spent the past week starting a new sprint on our latest large project, and as we&#8217;re keen to get our clients as involved as possible during sprints, we decided to get down with some <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">Behaviour-Driven Development</a> (BDD) which allows them to contribute to writing the actual acceptance criteria for the user stories.  We&#8217;re pretty big on <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test-Driven Developmen</a>t here at WO Towers but sometimes it&#8217;s necessary to strike a balance between testing every minute detail and no testing.  BDD seems to meet that balance whilst providing good code coverage with tests.  Note: here I speak of functional tests rather than unit tests.</p>
<p>The beauty of BDD is that it&#8217;s written in plain everyday language, and this can be directly translated to code snippets.  Therefore the client is happy working &#8220;in plain english&#8221;, and the developer can crack on with writing the actual code to test these parts.</p>
<p>We&#8217;ve chosen to use <a href="http://symfony.com/">Symfony2</a> for the project (more on that in a separate post) and for the BDD aspect we&#8217;ve gone with <a href="http://behat.org/">Behat</a> (coupled with <a href="https://github.com/Behat/Mink">Mink</a>); both of which have bundles available for Symfony2. Essentially, BDD boils down to <strong>Features</strong>, consisting of a number of <strong>Scenarios</strong>, which in turn consist of a number of <strong>Steps</strong>.  Here&#8217;s an example:</p>
<pre>Feature: Login to the admin area
	As an administrator
	I want to be able to log into an admin area
	So I can administer MyApp

	Scenario: Joe Bloggs logs into the admin area
	  Given I visit the admin area
	  When I am shown the login form
	  And I click login with my correct credentials
	  Then I should be on /admin/home
</pre>
<p>This could translate to code such as the following:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Given</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^I visit the admin area$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPathTo</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/admin&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">When</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^I am shown the login form$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$doc</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    assertTrue<span style="color: #009900;">&#40;</span><span style="color: #000088;">$doc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;_username&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    assertTrue<span style="color: #009900;">&#40;</span><span style="color: #000088;">$doc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;_password&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">And</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^I click login with my correct credentials$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$doc</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$doc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fillField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;_username&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;joe&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$doc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fillField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;_password&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;bloggs&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$doc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clickButton</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Log in&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Then</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^(?:|I )should be on (?P&lt;page&gt;.+)$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    assertEquals<span style="color: #009900;">&#40;</span>
        <span style="color: #990000;">parse_url</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPathTo</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> PHP_URL_PATH<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        <span style="color: #990000;">parse_url</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCurrentUrl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> PHP_URL_PATH<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The beauty of Behat is that the step definitions are reusable, meaning that if you stick to a standard way of describing your steps, the amount of code you need to write is vastly reduced, compared with normal functional TDD.  Steps that aren&#8217;t implemented yet are given default code as per:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Given</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^I visit the admin area$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    throw <span style="color: #000000; font-weight: bold;">new</span> \Behat\Behat\Exception\PendingException<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;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>which will translate into the output shown as a step needing to be implemented.  Behat also takes note of the Pending exception being thrown and automatically skips any steps following this in the scenario, notifying you of this at the end of the test run.</p>
<p>Behat also comes with a number of standard step definitions built-in, although these are somewhat buried in the code and not in the docs :-(  So for example the following steps are part of the included ones:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">I go to <span style="color: #339933;">/</span>my<span style="color: #339933;">/</span>url<span style="color: #339933;">:</span>
&nbsp;
<span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">When</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^(?:|I )go to (?P&lt;page&gt;.+)$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPathTo</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>and</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">I fill in <span style="color: #0000ff;">&quot;username&quot;</span> with <span style="color: #0000ff;">&quot;foo&quot;</span><span style="color: #339933;">:</span>
&nbsp;
<span style="color: #000088;">$steps</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">When</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^(?:|I )fill in &quot;(?P&lt;field&gt;[^&quot;]*)&quot; with &quot;(?P&lt;value&gt;[^&quot;]*)&quot;$/'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$world</span><span style="color: #339933;">,</span> <span style="color: #000088;">$field</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$world</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fillField</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>which translates as even less code to write. Bonus!</p>
<h2>Tips &#8216;n&#8217; tricks</h2>
<p>The Mink (browser emulator abstraction layer) setup comes with a Symfony2 driver which is great for just testing normal usage.  In our project however we&#8217;re integrating Facebook authentication using the FOS <a href="https://github.com/FriendsOfSymfony/FacebookBundle">FacebookBundle</a>, and we needed a way to test that the user was being bounced to Facebook in order to log in.  The solution for this was simple &#8211; switch to using <a href="https://github.com/fabpot/Goutte">Goutte</a> as the driver, as per the BehatBundle docs, and voila, you can test the current URL contains eg facebook.com or whatever.  The actual testing of the authentication itself I&#8217;ll write up in a separate blog post as it&#8217;s a bit epic for here.</p>
<p>The documentation mentions using a separate front controller for testing, with a separate environment configuration.  This is definitely recommended, particularly if you&#8217;re using Goutte.  If you need services to be available, for example your entity manager, pop something like this in your env.php file:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$kernel</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AppKernel<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'test'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$kernel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadClassCache</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$service</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$kernel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContainer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;your.service.here&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>You can also use the <code>env.php</code> file for setting up fixtures that need to be reset for each Scenario that you create, eg pre-defined user states and so on.</p>
<h2>Caveats</h2>
<p>Unless you&#8217;re using <a href="https://github.com/Behat/SahiClient">Sahi</a>, you obviously can&#8217;t test things such as Javascript popups effectively.  I&#8217;m in two minds as to whether this should be handled by a new type of Exception which can be thrown e.g. a <code>TestInRealBrowserException()</code>.  That way it could be caught and notified to the user running the tests, or flagged as part of an automated build process for manual testing.</p>
<p>Overall, getting into BDD has been a fun and rewarding experience.  At times the lack of docs make it somewhat frustrating, but this is easily solved by a) digging into the code and b) probably me getting off my ass and submitting some docs back.  The ease of which the steps can be written though is a massive time saver when writing your tests, coupled with the reusability of the code.  Big thumbs-up from me!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2011/06/15/getting-into-behat-with-symfony2/feed/</wfw:commentRss>
		<slash:comments>8</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.]]></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>
]]></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.]]></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>
]]></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>Paper Prototyping Example</title>
		<link>http://www.whiteoctober.co.uk/blog/2010/12/15/paper-prototyping-example/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2010/12/15/paper-prototyping-example/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 09:11:21 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Uncategorised]]></category>
		<category><![CDATA[User experience]]></category>
		<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=662</guid>
		<description><![CDATA[This is an early paper prototype that Mariana created during the development of the engauge tool for the FoodRisC www.foodrisc.org project. This low-fi method of exploring our ideas helps us make mistakes early and cheaply.]]></description>
			<content:encoded><![CDATA[<p>This is an early paper prototype that Mariana created during the development of the engauge tool for the FoodRisC <a href="http://www.foodrisc.org">www.foodrisc.org</a> project. This low-fi method of exploring our ideas helps us make mistakes early and cheaply.</p>
<p><iframe src="http://player.vimeo.com/video/17837617?portrait=0&amp;color=1C6E86" width="420" height="299" frameborder="0"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2010/12/15/paper-prototyping-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript Inheritance done right</title>
		<link>http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/</link>
		<comments>http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/#comments</comments>
		<pubDate>Wed, 20 Oct 2010 15:11:18 +0000</pubDate>
		<dc:creator>John</dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[Web technologies]]></category>

		<guid isPermaLink="false">http://www.whiteoctober.co.uk/blog/?p=638</guid>
		<description><![CDATA[Currently I am doing a lot of non-framework based JavaScript. JavaScript&#8217;s implementation of Object Orientated principles is different than most languages but the theory is simple. Quick googling shows lots of examples on how to extend from a parent to do inheritance in JavaScript, however none of the examples tell you that the parents constructor [...]]]></description>
			<content:encoded><![CDATA[<p>Currently I am doing a lot of non-framework based JavaScript. JavaScript&#8217;s implementation of Object Orientated principles is different than most languages but the theory is simple.</p>
<p>Quick googling shows lots of examples on how to extend from a parent to do inheritance in JavaScript, however none of the examples tell you that the parents constructor won&#8217;t be called. So &#8220;new&#8221; objects will keep the properties of earlier objects.</p>
<p>The solution is to call the parents constructor.<br />
<strong>TestObject.call( this, data);</strong></p>
<p>A detailed example of the problem is below and the answer provided on <a href="http://stackoverflow.com/questions/3959438/inheritance-in-javascript-variables-in-the-parent">StackOverflow</a>, using the excellent <a href="http://www.stacktack.com">StackTack</a> app.<br />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript">// <![CDATA[
<script type="text/javascript" src="http://app.stacktack.com/jquery.stacktack.min.js">
// ]]&gt;</script><script type="text/javascript">// <![CDATA[
  $(document).ready(function() {        $(document).stacktack({width: '407px', onlyShowAcceptedAnswer: true});     });
// ]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.whiteoctober.co.uk/blog/2010/10/20/javascript-inheritance-done-right/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 [...]]]></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>
]]></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 [...]]]></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>
]]></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>
	</channel>
</rss>

