<?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>Rich&#039;s stuff</title>
	<atom:link href="http://www.richsage.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.richsage.co.uk</link>
	<description>ramblings, musings, web stuff</description>
	<lastBuildDate>Thu, 12 Apr 2012 08:14:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Doctrine 2 &#8211; detaching all entities</title>
		<link>http://www.richsage.co.uk/2012/03/28/doctrine-2-detaching-all-entities/</link>
		<comments>http://www.richsage.co.uk/2012/03/28/doctrine-2-detaching-all-entities/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 15:03:25 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[doctrine]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=240</guid>
		<description><![CDATA[We ran into a little problem at work this afternoon. Running a full set of Behat features caused one of the scenarios to fail in the middle &#8211; it was a scenario detailing user signup via an API, where the response indicated that the expected security token was from a different user object. Strange as [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F03%2F28%2Fdoctrine-2-detaching-all-entities%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F03%2F28%2Fdoctrine-2-detaching-all-entities%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>We ran into a little problem at <a href="http://www.whiteoctober.co.uk/" title="White October">work</a> this afternoon.  Running a full set of <a href="http://behat.org/" title="Behat">Behat</a> features caused one of the scenarios to fail in the middle &#8211; it was a scenario detailing user signup via an API, where the response indicated that the expected security token was from a different user object.  Strange as the database indicated there was only a single entity that had been persisted.  Running the scenario on its own, everything was fine.</p>
<p>The solution was discovered via <a href="http://stackoverflow.com/questions/7956027/how-to-stop-doctrine-2-from-caching-a-result-in-symfony-2/7957067#7957067">this helpful StackOverflow post</a> (yay for SO).  It seems that Doctrine 2 keeps a reference to persisted entities, to save time looking them up again.  Which we&#8217;d explicitly wanted to do.  Since our scenarios have a drop-and-reload-style setup, we didn&#8217;t want any previous entities hanging around. Based on the StackOverflow answer, the solution was to adjust the end of our <code>setUp()</code> method to add the last line shown in the code example below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Sets up our database
 */</span>
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Our usual setup stuff goes here</span>
    <span style="color: #666666; font-style: italic;">// eg drop tables, load schema, any</span>
    <span style="color: #666666; font-style: italic;">// fixture loading and so on.</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dropTables</span><span style="color: #009900;">&#40;</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;">generateSchema</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;">// Here we now detach any previously-queried entities</span>
    <span style="color: #666666; font-style: italic;">// to avoid caching issues.</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">em</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clear</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>where <code>$this->em</code> is an instance of the Doctrine <code>EntityManager</code>. Simples.</p>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=240&amp;md5=fcf7124a19b929f1896b085191bc3bde" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2012/03/28/doctrine-2-detaching-all-entities/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F03%2F28%2Fdoctrine-2-detaching-all-entities%2F&amp;language=en_GB&amp;category=software&amp;title=Doctrine+2+%26%238211%3B+detaching+all+entities&amp;description=We+ran+into+a+little+problem+at+work+this+afternoon.+Running+a+full+set+of+Behat+features+caused+one+of+the+scenarios+to+fail+in+the+middle+%26%238211%3B+it+was...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Experimentation with ZeroMQ</title>
		<link>http://www.richsage.co.uk/2012/01/25/experimentation-with-zeromq/</link>
		<comments>http://www.richsage.co.uk/2012/01/25/experimentation-with-zeromq/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 21:10:15 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=222</guid>
		<description><![CDATA[At the weekend I was experimenting with ZeroMQ (0MQ for short here) for handling requests for items in an online shop. The idea behind it was simple &#8211; schedule requests for items to be added to a shopping cart, and don&#8217;t allow overselling of said stock items. The legacy code handles requests by wrapping in [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F01%2F25%2Fexperimentation-with-zeromq%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F01%2F25%2Fexperimentation-with-zeromq%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>At the weekend I was experimenting with <a href="http://www.zeromq.org/" title="ZeroMQ">ZeroMQ</a> (0MQ for short here) for handling requests for items in an online shop.  The idea behind it was simple &#8211; schedule requests for items to be added to a shopping cart, and don&#8217;t allow overselling of said stock items.  The legacy code handles requests by wrapping in a transaction and checking for the amount of items currently available (sales + in existing carts), then adding/rejecting as appropriate.</p>
<p>If however there is significant traffic, this can result in oversells as the number of items available can be reported the same to more than 1 user.  If both users request the final item, your oversell happens.  I wanted to remove the likelihood of this happening, and so I turned to a queueing system to see how this could make a difference. I&#8217;d seen the video of Ian Barber&#8217;s <a href="http://www.phpconference.co.uk/talk/zeromq-answer">presentation at PHP UK last year</a>, and liked the apparent simplicity of 0MQ coupled with the lightweight in-memory approach so decided to experiment a bit.</p>
<p>After <a href="http://www.zeromq.org/intro:get-the-software">downloading</a> and installing the 0MQ library, and the <a href="http://www.zeromq.org/bindings:php">pecl extension</a> for PHP, I was all set to go.</p>
<p>The idea seemed simple:</p>
<ul>
<li>Take all requests for items, and pop them into a queue</li>
<li>If a response from the queue isn&#8217;t available immediately, the customer should be shown a page which polls periodically for the result.</li>
<li>When the result is available, redirect the customer to their cart (success) or back to the item page (failure)</li>
</ul>
<p>The <a href="http://zguide.zeromq.org/page:all">0MQ documentation</a> at first seemed thorough, but reading through I realised it was a bit too verbose for my liking. I can appreciate the use of metaphors and friendly language, but it seemed to hinder understanding of what 0MQ could offer, coupled with everything being on the same page.  Slightly overwhelming!  In contrast, RabbitMQ&#8217;s <a href="http://www.rabbitmq.com/getstarted.html">tutorial pages</a> seemed to be a lot clearer.  For a developer new to queueing system, this was definitely a win for RabbitMQ &#8211; a case of which-image-represents-best-what-I-want *click* etc.  However, I stuck with 0MQ for now for the reasons outlined above.</p>
<p>I settled on the Push-Pull methodology, &#8220;<a href="http://zguide.zeromq.org/page:all#toc9">Divide and Conquer</a>&#8221; in the 0MQ docs.  This would satisfy the requirements above of being able to dump a request into a queue and periodically (via another mechanism) check for a result.  I&#8217;ve shamelessly ripped off the accompanying image from their docs here in order to illustrate my point :-)</p>
<p><a href="http://www.richsage.co.uk/wp-content/uploads/2012/01/fig5.png"><img src="http://www.richsage.co.uk/wp-content/uploads/2012/01/fig5.png" alt="" title="0MQ&#039;s Push-Pull model" width="456" height="582" class="aligncenter size-full wp-image-231" /></a></p>
<p>In the above image, the part labelled &#8220;Ventilator&#8221; can be equated to the user requesting a quantity of items to add to a shopping cart, and my queue handler is a single instance of a worker.  In my implementation, I went for something like the following process:</p>
<ul>
<li>User requests 1 of item A via form</li>
<li>Memcache entry is created with a unique key for the user&#8217;s request</li>
<li>0MQ request is created, &#8220;allocate me 1 of item A, for my session ID X and unique key ABC&#8221;</li>
<li><em>&#8230; polling happens here &#8230;</em></li>
<li>0MQ worker receives message and performs relevant checks</li>
<li>Memcache value for supplied unique key is updated with response</li>
<li>Polling for this updated value causes a redirect for the user accordingly</li>
</ul>
<p>Polling checked the memcache key for a successful response.  I decided to use <a href="http://memcached.org/">memcache</a> for this as it was quick to get going and I only technically needed a key-value setup.  I also wanted to avoid unnecessary hits on a database if possible, preferring to keep this for transactional data.  Plus I also wanted to play with memcache a bit ;-)</p>
<h2>Testing</h2>
<p>In tests, this setup seemed to work well, and the updated memcache value ended up being a serialized array with a success/error code, and some additional information eg &#8220;Sold out&#8221;, &#8220;Item is unavailable&#8221;, &#8220;You requested 2 but only 1 is available&#8221;.  This enabled better feedback for the user when their request was unsuccessful.</p>
<p>Running this in small-scale tests was great.  It was good to be able to start and stop the queue handler, and see the user being automatically bounced to the &#8220;please wait&#8221; polling page whenever the queue handler wasn&#8217;t running or had a backlog of messages to process. Fire up the handler, checks take place and the user is then redirected accordingly.</p>
<p>When running this under heavier loads however, we hit instances where occasionally (due to intentionally-bad <a href="http://httpd.apache.org">Apache</a> settings), the server processes ran out of memory and required a restart of Apache.  This was done deliberately to see how the queue could recover from different scenarios.  As a result, restarting Apache would cause a flood of messages to be sent to the queue handler in one go, presumably because they&#8217;d been blocked somehow previously with the large load.  This was confusing and unexpected behaviour to me, however I presumed this was because Apache (with mod_php) had been struggling to send the messages out under the load, and a restart caused a flush of some sorts.  I also presume this isn&#8217;t down to any fault of 0MQ.  It does however pose the question of what to do in a scenario where messages can potentially be lost, but this could be solved by a message queue that persists messages somewhere until completion.</p>
<p>Despite this teething issue which wasn&#8217;t really down to any fault of 0MQ, the system works great.  Being new to queueing like this, I&#8217;m not entirely sure how this would scale and still keep the ability to not oversell an item &#8211; database transactions from multiple workers would need to be synchronised somehow to ensure that figures are kept up to date.  But overall, I&#8217;m very happy with it as a starting point for a replacement solution.</p>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=222&amp;md5=8c2ca9636d9b23d72ded219b18b122b9" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2012/01/25/experimentation-with-zeromq/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F01%2F25%2Fexperimentation-with-zeromq%2F&amp;language=en_GB&amp;category=software&amp;title=Experimentation+with+ZeroMQ&amp;description=At+the+weekend+I+was+experimenting+with+ZeroMQ+%280MQ+for+short+here%29+for+handling+requests+for+items+in+an+online+shop.+The+idea+behind+it+was+simple+%26%238211%3B+schedule+requests...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Steps to release a PEAR package (for lead devs)</title>
		<link>http://www.richsage.co.uk/2012/01/05/steps-to-release-a-pear-package-for-lead-devs/</link>
		<comments>http://www.richsage.co.uk/2012/01/05/steps-to-release-a-pear-package-for-lead-devs/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 09:36:33 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[pear]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=216</guid>
		<description><![CDATA[Mini post. I can never find this information on the PEAR site, so this is just a reference for me really :-) After all code changes have been made and pushed into the repository, do the following &#91;rich@localhost&#93;# pfm * Follow instructions here, eg update version number, release notes * Regenerate Contents * Save &#38; [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F01%2F05%2Fsteps-to-release-a-pear-package-for-lead-devs%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F01%2F05%2Fsteps-to-release-a-pear-package-for-lead-devs%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>Mini post. I can never find this information on the PEAR site, so this is just a reference for me really :-)</p>
<p>After all code changes have been made and pushed into the repository, do the following</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>rich<span style="color: #000000; font-weight: bold;">@</span>localhost<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># pfm</span>
<span style="color: #000000; font-weight: bold;">*</span> Follow instructions here, eg update version number, release notes
<span style="color: #000000; font-weight: bold;">*</span> Regenerate Contents
<span style="color: #000000; font-weight: bold;">*</span> Save <span style="color: #000000; font-weight: bold;">&amp;</span> Exit
<span style="color: #7a0874; font-weight: bold;">&#91;</span>rich<span style="color: #000000; font-weight: bold;">@</span>localhost<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># git add package.xml</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>rich<span style="color: #000000; font-weight: bold;">@</span>localhost<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># git commit</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>rich<span style="color: #000000; font-weight: bold;">@</span>localhost<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># git tag &quot;RELEASE-x.y.z&quot;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>rich<span style="color: #000000; font-weight: bold;">@</span>localhost<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># pear package</span>
<span style="color: #000000; font-weight: bold;">*</span> Package <span style="color: #c20cb9; font-weight: bold;">file</span> is created, release this through PEAR website <span style="color: #c20cb9; font-weight: bold;">as</span> normal</pre></div></div>

 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=216&amp;md5=d03721363093bc0667ac00da81f047c0" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2012/01/05/steps-to-release-a-pear-package-for-lead-devs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2012%2F01%2F05%2Fsteps-to-release-a-pear-package-for-lead-devs%2F&amp;language=en_GB&amp;category=software&amp;title=Steps+to+release+a+PEAR+package+%28for+lead+devs%29&amp;description=Mini+post.+I+can+never+find+this+information+on+the+PEAR+site%2C+so+this+is+just+a+reference+for+me+really+%3A-%29+After+all+code+changes+have+been+made+and...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Rendering emails with Twig in Symfony2</title>
		<link>http://www.richsage.co.uk/2011/12/16/rendering-emails-with-twig-in-symfony2/</link>
		<comments>http://www.richsage.co.uk/2011/12/16/rendering-emails-with-twig-in-symfony2/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 17:09:55 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=204</guid>
		<description><![CDATA[I&#8217;ve been experimenting with sending emails but rendering the content with Twig. This allows emails to extend a standard layout where required, but also gives us the flexibility to insert other content into the template which may be required. In the first instance, we&#8217;re interested in supplying the email subject here. The concept is simple [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F16%2Frendering-emails-with-twig-in-symfony2%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F16%2Frendering-emails-with-twig-in-symfony2%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>I&#8217;ve been experimenting with sending emails but rendering the content with <a href="http://twig.sensiolabs.org/">Twig</a>.  This allows emails to extend a standard layout where required, but also gives us the flexibility to insert other content into the template which may be required.  In the first instance, we&#8217;re interested in supplying the email subject here.</p>
<p>The concept is simple &#8211; within <a href="http://symfony.com">Symfony2</a>, firstly get Twig from the container or inject it accordingly.  You can then render the template as a whole, and also extract any other items required.  My example is taken from a listener class I&#8217;ve been using, but the concepts can be applied appropriately depending on where you want to use it:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> MyListener
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$mailer</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$twig</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>\Swift_Mailer <span style="color: #000088;">$mailer</span><span style="color: #339933;">,</span> \Twig_Environment <span style="color: #000088;">$twig</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;">mailer</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mailer</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">twig</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$twig</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> onMyevent<span style="color: #009900;">&#40;</span><span style="color: #000088;">$myEvent</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$emailTo</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$myEvent</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEmailTo</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;">// Load the template in</span>
        <span style="color: #000088;">$templateFile</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;MyBundle:emails:myEmailTemplate.twig&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$templateContent</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">twig</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadTemplate</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$templateFile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Render the whole template including any layouts etc</span>
        <span style="color: #000088;">$body</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$templateContent</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;someParam&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;foo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Get the subject block out</span>
        <span style="color: #666666; font-style: italic;">// If the block doesn't exist, use a default</span>
        <span style="color: #000088;">$subject</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$templateContent</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasBlock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;subject&quot;</span><span style="color: #009900;">&#41;</span>
            ? <span style="color: #000088;">$templateContent</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderBlock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;subject&quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;param1&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$someInformation</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">foo</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;Default subject here&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$subject</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$subject</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Send email</span>
        <span style="color: #000088;">$message</span> <span style="color: #339933;">=</span> \Swift_Message<span style="color: #339933;">::</span><span style="color: #004000;">newInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setSubject</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$subject</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFrom</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;info@example.com&quot;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTo</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$emailTo</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setBody</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$body</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;">mailer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">send</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$message</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>This means we can put something like the following in our template file:</p>

<div class="wp_syntax"><div class="code"><pre class="twig" style="font-family:monospace;"><span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%</span> <span style="color: #0600FF;">extends</span> <span style="color: #ff0000;">&quot;MyBundle:emails:emailLayout.twig&quot;</span> <span style="color: #D36900;">%</span><span style="color: #D36900;">&#125;</span>
&nbsp;
<span style="color: #008080; font-style: italic;">{# This block is rendered in emailLayout.twig #}</span>
<span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%</span> <span style="color: #0600FF;">block</span> body <span style="color: #D36900;">%</span><span style="color: #D36900;">&#125;</span>
Hello, world. This is your email content here
<span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%</span> <span style="color: #0600FF;">endblock</span> <span style="color: #D36900;">%</span><span style="color: #D36900;">&#125;</span>
&nbsp;
<span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%</span> <span style="color: #0600FF;">block</span> subject <span style="color: #D36900;">%</span><span style="color: #D36900;">&#125;</span>
Your subject line goes here
<span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%</span> <span style="color: #0600FF;">endblock</span> <span style="color: #D36900;">%</span><span style="color: #D36900;">&#125;</span></pre></div></div>

<p>I was hoping to use the Twig <code>{% spaceless %}</code> tag, but it appears that it&#8217;s only available for HTML (sadly <a href="https://github.com/fabpot/Twig/pull/433">this PR</a> has been closed; shame as it would have been useful).  Hence the <code>trim()</code> call when retrieving the subject.</p>
<p>Of course, you can extend the above to inject in default email-FROM-addresses and names, template names and so on where appropriate.</p>
<p><strong>Update</strong>: Thanks to Fabien for pointing out (comments below) that you can remove whitespace by using the following (hyphens at the end of the opening <code>block</code> tag and at the start of <code>endblock</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="twig" style="font-family:monospace;"><span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%</span> <span style="color: #0600FF;">block</span> subject <span style="color: #D36900;">-%</span><span style="color: #D36900;">&#125;</span>
Your subject line goes here
<span style="color: #D36900;">&#123;</span><span style="color: #D36900;">%-</span> <span style="color: #0600FF;">endblock</span> <span style="color: #D36900;">%</span><span style="color: #D36900;">&#125;</span></pre></div></div>

 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=204&amp;md5=ecca1a59894dbe7e83ae90bfd91d95e0" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/12/16/rendering-emails-with-twig-in-symfony2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F16%2Frendering-emails-with-twig-in-symfony2%2F&amp;language=en_GB&amp;category=software&amp;title=Rendering+emails+with+Twig+in+Symfony2&amp;description=I%26%238217%3Bve+been+experimenting+with+sending+emails+but+rendering+the+content+with+Twig.+This+allows+emails+to+extend+a+standard+layout+where+required%2C+but+also+gives+us+the+flexibility+to+insert...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>First steps into conference speaking</title>
		<link>http://www.richsage.co.uk/2011/12/08/first-steps-into-conference-speaking/</link>
		<comments>http://www.richsage.co.uk/2011/12/08/first-steps-into-conference-speaking/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 09:07:29 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[conference]]></category>
		<category><![CDATA[presentation]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=202</guid>
		<description><![CDATA[I&#8217;ve been thinking about next year&#8217;s New Year&#8217;s Resolutions again. One which I&#8217;m going to repeat from this year was to blog more (inspired by Lorna&#8217;s post about blogging more back in January), but also a new one I want to achieve is to speak at a conference. I&#8217;ve presented papers at a couple of [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F08%2Ffirst-steps-into-conference-speaking%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F08%2Ffirst-steps-into-conference-speaking%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>I&#8217;ve been thinking about next year&#8217;s New Year&#8217;s Resolutions again.  One which I&#8217;m going to repeat from this year was to blog more (inspired by Lorna&#8217;s <a href="http://www.lornajane.net/posts/2011/make-blogging-your-new-years-resolution">post about blogging more</a> back in January), but also a new one I want to achieve is to speak at a conference.</p>
<p>I&#8217;ve presented papers at a <a href="http://www.eva-london.org/">couple</a> of non-web related <a href="http://www2.ph.ed.ac.uk/acoustics/MAN/bradfordmeeting2006.html">conferences</a> a number of years ago, but nothing in the web field, and I&#8217;m unsure as to the correct approach to take with this.  My main reason for wanting to speak is that I want to be able to share knowledge I&#8217;ve learnt in the hope that this may be of interest to at least one person.  I&#8217;m also passionate about the technology I use in day-to-day development and would most probably like to include this.  My main concern however is &#8220;would it be interesting enough?&#8221;, which I&#8217;m inclined to feel is a catch-22 situation &#8211; I won&#8217;t know until presenting it, but then I won&#8217;t get a chance to present it unless I submit.</p>
<p>Calls for papers are continuously springing up, and I&#8217;m wondering about the best approach here to get my foot in the door so to speak.  Is it a case of writing up something that I feel is interesting and would benefit others, and just taking the leap? Finding local Uncons/user groups and trying the material out there?</p>
<p>I&#8217;d be interested to hear any tips and pointers :-)</p>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=202&amp;md5=b12b24a8fe98ef69d015c71f0b2eea3e" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/12/08/first-steps-into-conference-speaking/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F08%2Ffirst-steps-into-conference-speaking%2F&amp;language=en_GB&amp;category=software&amp;title=First+steps+into+conference+speaking&amp;description=I%26%238217%3Bve+been+thinking+about+next+year%26%238217%3Bs+New+Year%26%238217%3Bs+Resolutions+again.+One+which+I%26%238217%3Bm+going+to+repeat+from+this+year+was+to+blog+more+%28inspired+by+Lorna%26%238217%3Bs+post+about+blogging+more...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Symfony2 data collectors</title>
		<link>http://www.richsage.co.uk/2011/12/05/symfony2-data-collectors/</link>
		<comments>http://www.richsage.co.uk/2011/12/05/symfony2-data-collectors/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 16:38:47 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=196</guid>
		<description><![CDATA[NB: Cross-posted on our work blog at White October :-) 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 [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F05%2Fsymfony2-data-collectors%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F05%2Fsymfony2-data-collectors%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>NB: </strong>Cross-posted on our <a href="http://www.whiteoctober.co.uk/blog/">work blog</a> at <a href="http://www.whiteoctober.co.uk/">White October</a> :-)</p>
<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: #339933;">&lt;</span> ?php
&nbsp;
<span style="color: #000000; font-weight: bold;">namespace</span> Jirafe\Bundle\MailChimpBundle\DataCollector<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\HttpKernel\DataCollector\DataCollector<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\HttpFoundation\Request<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\HttpFoundation\Response<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> 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>
      <span style="color: #b1b100;">throw</span> <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>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=196&amp;md5=c0ec9fa62668e244db37cd8d47be6b2e" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/12/05/symfony2-data-collectors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F12%2F05%2Fsymfony2-data-collectors%2F&amp;language=en_GB&amp;category=software&amp;title=Symfony2+data+collectors&amp;description=NB%3A+Cross-posted+on+our+work+blog+at+White+October+%3A-%29+I+spent+some+time+last+week+working+on+automated+MailChimp+integration+with+one+of+our+Symfony2+sites.+The+project+uses...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Twig extensions &#8211; name them correctly!</title>
		<link>http://www.richsage.co.uk/2011/09/20/twig-extensions-name-them-correctly/</link>
		<comments>http://www.richsage.co.uk/2011/09/20/twig-extensions-name-them-correctly/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 14:17:56 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=189</guid>
		<description><![CDATA[Came across this one today whilst integrating some new code into my current Symfony2 project. The project has 2 custom Twig extensions &#8211; one with some filters in, one with some custom methods. When creating the latter, I&#8217;d copied the class from the former and tweaked to suit. In doing so, I&#8217;d left these lines [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F09%2F20%2Ftwig-extensions-name-them-correctly%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F09%2F20%2Ftwig-extensions-name-them-correctly%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>Came across this one today whilst integrating some new code into my current <a href="http://symfony2.com/">Symfony2</a> project.  The project has 2 custom <a href="http://twig.sensiolabs.org">Twig</a> extensions &#8211; one with some filters in, one with some custom methods.  When creating the latter, I&#8217;d copied the class from the former and tweaked to suit.  In doing so, I&#8217;d left these lines in:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #009933; font-style: italic;">/**
     * Name of this extension
     *
     * @return string
     */</span>
    <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;">&quot;myfirstextension&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>The Twig documentation states that all extensions should be named uniquely, unless you need to replace any existing extensions, in which case you should name them the same.  <a href="http://twig.sensiolabs.org/doc/extensions.html#overriding-default-filters">See here</a> for a better explanation :-)  Great for extensibility and adjusting extensions that maybe you don&#8217;t have control over. Not so good when both extensions do something different and you don&#8217;t quite understand why it&#8217;s not working&#8230;.</p>
<p>Anyway, quick question in the #symfony IRC channel and <a href="http://twitter.com/Stof70">Stof</a> came to the rescue. Give that man a medal :-) and name your extensions uniquely if you don&#8217;t want them to overwrite others!</p>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=189&amp;md5=bd7de3c08afa5bcc9e8172371e243de9" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/09/20/twig-extensions-name-them-correctly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F09%2F20%2Ftwig-extensions-name-them-correctly%2F&amp;language=en_GB&amp;category=software&amp;title=Twig+extensions+%26%238211%3B+name+them+correctly%21&amp;description=Came+across+this+one+today+whilst+integrating+some+new+code+into+my+current+Symfony2+project.+The+project+has+2+custom+Twig+extensions+%26%238211%3B+one+with+some+filters+in%2C+one+with...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Logging out a user programmatically in Symfony2</title>
		<link>http://www.richsage.co.uk/2011/08/25/logging-out-a-user-programmatically-in-symfony2/</link>
		<comments>http://www.richsage.co.uk/2011/08/25/logging-out-a-user-programmatically-in-symfony2/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 14:03:03 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=182</guid>
		<description><![CDATA[Quick post this, as I know I&#8217;ll forget/lose this code otherwise&#8230; Sometimes you need the ability to force a logout of a user. The example I&#8217;ll use here is a user requesting their account be deactivated &#8211; you assume that upon confirmation of the deactivation the user&#8217;s model is marked as such, and the user [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F08%2F25%2Flogging-out-a-user-programmatically-in-symfony2%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F08%2F25%2Flogging-out-a-user-programmatically-in-symfony2%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>Quick post this, as I know I&#8217;ll forget/lose this code otherwise&#8230; Sometimes you need the ability to force a logout of a user.  The example I&#8217;ll use here is a user requesting their account be deactivated &#8211; you assume that upon confirmation of the deactivation the user&#8217;s model is marked as such, and the user is subsequently logged out and shown a confirmation page:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Update your model here. Example:</span>
<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> clone <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;security.context&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getToken</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</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;">// Log the user out</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;request&quot;</span><span style="color: #009900;">&#41;</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;">invalidate</span><span style="color: #009900;">&#40;</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;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;security.context&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setToken</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Flash var to enable the user to see the deactivation success page</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;session&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFlash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'deactivate_account.success'</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>
&nbsp;
<span style="color: #666666; font-style: italic;">// and redirect to success page</span>
<span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">new</span> RedirectResponse<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;router&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;deactivate_account_success&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Your deactivation page should allow viewing without requiring authentication (anonymous users can view it).  The above code should be self-explanatory &#8211; invalidate the current session, and set the security token to null (rather than the previously-authenticated token).  The flash variable I set so that viewing of the success page is one-shot rather than being permanently viewable.  Just my preference :-)</p>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=182&amp;md5=7707f6c85be4c5b0fd853e75ab6855b5" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/08/25/logging-out-a-user-programmatically-in-symfony2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F08%2F25%2Flogging-out-a-user-programmatically-in-symfony2%2F&amp;language=en_GB&amp;category=software&amp;title=Logging+out+a+user+programmatically+in+Symfony2&amp;description=Quick+post+this%2C+as+I+know+I%26%238217%3Bll+forget%2Flose+this+code+otherwise%26%238230%3B+Sometimes+you+need+the+ability+to+force+a+logout+of+a+user.+The+example+I%26%238217%3Bll+use+here+is+a...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Greyscale printing on a Canon MP270 in Linux</title>
		<link>http://www.richsage.co.uk/2011/08/06/greyscale-printing-on-a-canon-mp270-in-linux/</link>
		<comments>http://www.richsage.co.uk/2011/08/06/greyscale-printing-on-a-canon-mp270-in-linux/#comments</comments>
		<pubDate>Sat, 06 Aug 2011 10:53:54 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[print]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=174</guid>
		<description><![CDATA[Just came across this article on ubuntuforums.org which describes how to add a greyscale printing option when using a Canon MP270 printer under Ubuntu. Reprinting here in case the original disappears. Dead simple!: After reading the manual from Canon, I have made the grayscale printing working too. For those who need it, here is the [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F08%2F06%2Fgreyscale-printing-on-a-canon-mp270-in-linux%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F08%2F06%2Fgreyscale-printing-on-a-canon-mp270-in-linux%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>Just came across <a href="http://ubuntuforums.org/showpost.php?p=8971846&#038;postcount=21">this article</a> on <a href="http://ubuntuforums.org">ubuntuforums.org</a> which describes how to add a greyscale printing option when using a <a href="http://www.canon.co.uk/For_Home/Product_Finder/Multifunctionals/Inkjet/PIXMA_MP270/">Canon MP270</a> printer under Ubuntu. Reprinting here in case the original disappears. Dead simple!:</p>
<blockquote><p>After reading the manual from Canon, I have made the grayscale printing working too. For those who need it, here is the fast tip:</p>
<p>Under System&#8211;>Administration&#8211;>Printing</p>
<p>right click MP250 that you have already setup, then select Properties from the popup menu, go to Job Options, scroll down to the bottom, add this option in:</p>
<p>CNGrayscale</p>
<p>click the Add button to add the option to the list.</p>
<p>Beside the CNGrayscale option, type in TRUE in the textfield, then click Apply, and close the Properties dialog.</p>
<p>By doing this, this printer is setup to be Grayscale printing by default. You can definitely have another copy of printer setup, pointing to the same printer, but for color printing. This is what i have done.
</p></blockquote>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=174&amp;md5=f24dd69e1556bb195ad4fecf286f7f25" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/08/06/greyscale-printing-on-a-canon-mp270-in-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F08%2F06%2Fgreyscale-printing-on-a-canon-mp270-in-linux%2F&amp;language=en_GB&amp;category=software&amp;title=Greyscale+printing+on+a+Canon+MP270+in+Linux&amp;description=Just+came+across+this+article+on+ubuntuforums.org+which+describes+how+to+add+a+greyscale+printing+option+when+using+a+Canon+MP270+printer+under+Ubuntu.+Reprinting+here+in+case+the+original...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Adding non-entity fields to your Symfony2 forms</title>
		<link>http://www.richsage.co.uk/2011/07/20/adding-non-entity-fields-to-your-symfony2-forms/</link>
		<comments>http://www.richsage.co.uk/2011/07/20/adding-non-entity-fields-to-your-symfony2-forms/#comments</comments>
		<pubDate>Wed, 20 Jul 2011 08:21:27 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.richsage.co.uk/?p=164</guid>
		<description><![CDATA[I&#8217;ve had a case recently whereby I needed to implement a registration form in my current Symfony2 application, based on a Mandango model. This form consisted of selected fields from my model, along with a separate &#8220;I accept the terms and conditions&#8221; checkbox; pretty standard. In Symfony 1, it was straightforward to add in non-model [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F07%2F20%2Fadding-non-entity-fields-to-your-symfony2-forms%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F07%2F20%2Fadding-non-entity-fields-to-your-symfony2-forms%2F&amp;source=rich_81&amp;style=normal&amp;service=is.gd" height="61" width="50" /><br />
			</a>
		</div>
<p>I&#8217;ve had a case recently whereby I needed to implement a registration form in my current <a href="http://symfony.com/">Symfony2</a> application, based on a <a href="http://www.mandango.org/">Mandango</a> model.  This form consisted of selected fields from my model, along with a separate &#8220;I accept the terms and conditions&#8221; checkbox; pretty standard.  In Symfony 1, it was straightforward to add in non-model fields, however in Symfony2 the <a href="http://symfony.com/doc/current/book/forms.html">convention for forms</a> is to create a domain model which represents your form, which then gets populated with the data.</p>
<p>Initially I went with extending from the Mandango model (in my case, <code>Model\MyOwnBundle\User</code> being the original model) and adding in a separate <code>get/setTermsAndConditions()</code> method, but this caused problems when saving the model down, as Mandango couldn&#8217;t find the document class (since I&#8217;d extended it and called it <code>UserRegistration</code>).</p>
<p>After a bit of digging and experimentation however, the following code does what I need it to, without having to extend my existing model or create a new one (which I&#8217;d then have to use to populate my actual Mandango model):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\Form\AbstractType<span style="color: #339933;">,</span>
    Symfony\Component\Form\CallbackValidator<span style="color: #339933;">,</span>
    Symfony\Component\Form\FormBuilder<span style="color: #339933;">,</span>
    Symfony\Component\Form\FormError<span style="color: #339933;">,</span>
    Symfony\Component\Form\FormInterface<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> RegisterFormType <span style="color: #000000; font-weight: bold;">extends</span> AbstractType
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * Constructs our registration form
     * 
     * @param \Symfony\Component\Form\FormBuilder $builder
     * @param array $options
     * @return void
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> buildForm<span style="color: #009900;">&#40;</span>FormBuilder <span style="color: #000088;">$builder</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Build the form</span>
        <span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span>
            <span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;firstName&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;text&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
            <span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;lastName&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;text&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
            <span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;emailAddress&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;email&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
            <span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;t_and_c&quot;</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">&quot;checkbox&quot;</span><span style="color: #339933;">,</span>
                <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                    <span style="color: #0000ff;">&quot;property_path&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                <span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// &quot;True&quot; validator on the form for t&amp;c</span>
        <span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span>
            <span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> CallbackValidator<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>FormInterface <span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;t_and_c&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addError</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> FormError<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Please accept the terms and conditions in order to register'</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;">&#125;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The above adds the <code>t_and_c</code> field but using <code>"property_path" => false</code> means it&#8217;s not validated against the model and therefore no need to implement separate <code>get/set()</code> methods. Instead we use a callback validator on the form to check the value of the <code>t_and_c</code> field and ensure it&#8217;s been checked. Et voila :-)</p>
 <p><a href="http://www.richsage.co.uk/?flattrss_redirect&amp;id=164&amp;md5=b9ad5a3401ff1db905ae31b7f4241e1b" title="Flattr" target="_blank"><img src="http://www.richsage.co.uk/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.richsage.co.uk/2011/07/20/adding-non-entity-fields-to-your-symfony2-forms/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=richsage&amp;popout=1&amp;url=http%3A%2F%2Fwww.richsage.co.uk%2F2011%2F07%2F20%2Fadding-non-entity-fields-to-your-symfony2-forms%2F&amp;language=en_GB&amp;category=software&amp;title=Adding+non-entity+fields+to+your+Symfony2+forms&amp;description=I%26%238217%3Bve+had+a+case+recently+whereby+I+needed+to+implement+a+registration+form+in+my+current+Symfony2+application%2C+based+on+a+Mandango+model.+This+form+consisted+of+selected+fields+from...&amp;tags=blog" type="text/html" />
	</item>
	</channel>
</rss>

