<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>LornaJane</title>
	
	<link>http://www.lornajane.net</link>
	<description>Lorna Jane Mitchell's Website</description>
	<lastBuildDate>Thu, 13 Jun 2013 09:27:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/lornajane" /><feedburner:info uri="lornajane" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Are Subqueries RESTful?</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/OS3CSLby2jA/are-subqueries-restful</link>
		<comments>http://www.lornajane.net/posts/2013/are-subqueries-restful#comments</comments>
		<pubDate>Thu, 13 Jun 2013 09:27:18 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2382</guid>
		<description><![CDATA[Twitter is great for one-liners, but it's very difficult to carry on any kind of advanced conversation there. Therefore when I saw this tweet yesterday, I knew I'd be picking a different medium to reply: @lornajane sory for getting on &#8230; <a href="http://www.lornajane.net/posts/2013/are-subqueries-restful">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>Twitter is great for one-liners, but it's very difficult to carry on any kind of advanced conversation there.  Therefore when I saw this tweet yesterday, I knew I'd be picking a different medium to reply:</p>
<blockquote class="twitter-tweet"><p>@<a href="https://twitter.com/lornajane">lornajane</a> sory for getting on your nervs with <a href="https://twitter.com/search/%23rest">#rest</a>,but are subquerys (like couchDB does) restfull to? is there a rule? like .../?type=bla</p>
<p>&mdash; Maximilian 'Berghoff (@ElectricMaxxx) <a href="https://twitter.com/ElectricMaxxx/status/344829706547367936">June 12, 2013</a></p></blockquote>
<p><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<p>The blog seems like a good place, as I can put examples and all kinds other things here, and waffle at length (which is really why I like it!).  Because when condensed to tweet form, the answer is really "it depends".</p>
<h3>The Problem(s)</h3>
<p>REST is all about representations of resources.  They might come in different formats, and they might appear at their own URI as well as in one or more collections, but essentially you just get a representation of a thing.  This is great, apart from when it isn't.</p>
<ul>
<li>What if you want a smaller result set with only a limited number of fields?</li>
<li>What if you want related data?  For every resource in a collection?</li>
</ul>
<p> <span id="more-2382"></span></p>
<p>There are a couple of tactics that I deploy each time I need to solve one of these problems, but they all revolve around remodelling the resource structure.  Just as we sometimes move fields around for database design or normalisation, we can do exactly the same with a RESTful service to make the resulting output make more sense to consumers. I thought I'd share examples of these tactics in this post.</p>
<h3>More Verbose, Less Verbose</h3>
<p>If a resource can be delivered in multiple formats, say XML or JSON, then why not in multiple "verbosities"?  Sometimes you only want the outline of a resource, for example if you're display news items, you might only want the title and posting date.  When you come to display that specific resource though, you'll want all the details, so you might end up with data structures like this:</p>
<p>Standard record:</p>
<ul>
<li>Title</li>
<li>Author</li>
<li>Date</li>
<li>Excerpt</li>
</ul>
<p>Verbose record:</p>
<ul>
<li>Title</li>
<li>Author</li>
<li>Date</li>
<li>Excerpt</li>
<li>Full Article</li>
<li>Collection of Related Articles</li>
</ul>
<p>If you want an in-the-wild example, try the Joind.in API.  All the records there come in a fairly minimal format, but you can request more fields by adding <code>verbose=yes</code> as a GET parameter.  Compare the API response (it's HTML, you can just click) for the recent DPC conference <a href="http://api.joind.in/v2.1/events/1109">http://api.joind.in/v2.1/events/1109</a> with its verbose version <a href="http://api.joind.in/v2.1/events/1109?verbose=yes">http://api.joind.in/v2.1/events/1109?verbose=yes</a>.</p>
<h3>Splitting into Subresources</h3>
<p>The alternative to allowing different verbosity of representations is to remove part of the record as it might be stored in the database into a separate resource.</p>
<p>So if your article is stored at <a href="#">http://example.com/articles/42</a>, this would show the abbreviated version of the record from the structure above.  Then you could offer the main body of the article at a separate location, such as <a href="#">http://example.com/articles/42/body</a>.  This does lead to repeated queries but if you only need the extra detail when you want to display a single record, it may well be worth the tradeoff - of course your mileage will vary between different applications.</p>
<h3>Nesting Likely Data</h3>
<p>The final tactic I want to share is where the server has a good idea that information will be needed from more than one source.  There's a good example in the wild from GitHub - if you grab a list of issues over their API, you'll get the full user object of the user that created each issue.  This makes sense because we'll always want to display who created the issue.</p>
<p>As an example, try requesting this URL with curl or your favourite API tool: <a href="https://api.github.com/repos/zendframework/zf2/issues">https://api.github.com/repos/zendframework/zf2/issues</a> and have a look at the structure that's returned (and as a total aside, admire the pretty-printing!  I love GitHub's API)</p>
<h3>Generic Solutions</h3>
<p>There certainly are generic solutions, where you can basically express the select statement in URL form, but I'm not a huge fan of this approach.  I'm sure there will be links to excellent resources in the comments of this article (thanks, people!)</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/OS3CSLby2jA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/are-subqueries-restful/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/are-subqueries-restful?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=are-subqueries-restful</feedburner:origLink></item>
		<item>
		<title>PHP Version Adoption</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/TXyGmGhe4Bs/php-version-adoption</link>
		<comments>http://www.lornajane.net/posts/2013/php-version-adoption#comments</comments>
		<pubDate>Tue, 04 Jun 2013 09:17:59 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php54]]></category>
		<category><![CDATA[php55]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2371</guid>
		<description><![CDATA[PHP runs over 75% of all websites whose technologies are known (source: w3techs), which makes for a really REALLY long tail of users who once installed wordpress, phpmyadmin, or some other open source project that helped their business needs at &#8230; <a href="http://www.lornajane.net/posts/2013/php-version-adoption">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>PHP runs over 75% of all websites whose technologies are known (source: <a href="http://w3techs.com/technologies/details/pl-php/5/all">w3techs</a>), which makes for a really REALLY long tail of users who once installed wordpress, phpmyadmin, or some other open source project that helped their business needs at the time.  What they don't do is <em>upgrade</em>.  PHP's current usage statistics look like this (source and raw numbers are <a href="https://gist.github.com/lornajane/5704679" in a gist</a> if you want them):</p>
<p><a href="http://www.lornajane.net/wp-content/uploads/2013/06/shiny-php-versions-white.png"><img src="http://www.lornajane.net/wp-content/uploads/2013/06/shiny-php-versions-white-1024x666.png" alt="PHP Version Adoption" width="584" height="379" class="alignnone size-large wp-image-2375" /></a></p>
<p>What's alarming about this is that the left half of this graph represents <em>unsupported versions of PHP</em>.  PHP 5.2 has been end of life since January 2011.  This doesn't mean that you can't use it any more, but it does mean that in terms of security updates, you are out of luck.  Some distributions will try to retro-fit some of the fixes but essentially your PHP applications seem a bit lacklustre because, well, you're using technology from 2006.<span id="more-2371"></span></p>
<h3>Where To Go From Here</h3>
<p>Nobody chooses a PHP 5.2 platform, these things just happen, and I absolutely don't mean this post as a rant - more as a way of raising the issue and trying to give some pointers for moving forward.  When I work with organisations to upgrade their platforms, usually either their hosting company is living in 2006, or they have a "supported" distro which prevents them from using modern technologies, or there's been no budget to upgrade, or ... really there are lots of (really valid) excuses.  However good things await in newer versions of PHP!</p>
<p><b>PHP 5.3</b> has actual useful OOP features!  We have anonymous functions (this feature will change your life, and for JS developers especially will make your PHP make more sense), the SPL extension is more than just iterators, and the DateTime extension is fabulous and finished in PHP 5.3.  Also in PHP 5.3 (released 2009, it's not cutting edge) is the vitally important <code>E_DEPRECATED</code> error reporting flag.  This will identify any features you are using in the current version of PHP which won't be available in the next version - if you are on PHP 5.3, or can get there, your upgrade path gets much easier!  If you have a living PHP application, I can't recommend this move strongly enough.</p>
<p><b>PHP 5.4</b> has some cute new features, but whether you need them or not, PHP 5.4 has faster execution time and reduced memory footprint.  Here's the graph from some benchmarks I did between versions of PHP last month - the Y axis is the number of seconds each version took, on average, to run the benchmark script included in the PHP source tree (raw numbers are <a href="https://gist.github.com/lornajane/5704679">available in a gist</a>):</p>
<p><a href="http://www.lornajane.net/wp-content/uploads/2013/06/performance-shot-labelled.png"><img src="http://www.lornajane.net/wp-content/uploads/2013/06/performance-shot-labelled-1024x587.png" alt="PHP Performance Across Versions" width="584" height="334" class="alignnone size-large wp-image-2373" /></a></p>
<p>Whether you want to be able to use traits or not, PHP 5.4 will improve the performance of your application and reduce your hardware costs ... all you have to do is upgrade between versions of free software.  Why isn't the PHP 5.4 segment on the first graph bigger?  There are some explanations, such as the lack of APC, for this version, but nothing that seem compelling to me (happy to hear your stories in the comments).</p>
<p><b>PHP 5.5</b> isn't actually production-ready, as we're still in the release candidate phase for it, but it's probably weeks away.  Look out though, a more regular release cycle for PHP means that there will be smaller incremental changes and we'll all be upgrading PHP the same way we maintain our other software - so pretty regularly.  Beyond PHP 5.3, the effort and risk in upgrading is much reduced.</p>
<h3>The Future</h3>
<p>In truth, the future is already here for those people on PHP 5.4 and beyond.  Keeping PHP upgraded is just part of our regular maintenance workflow, and the language is progressing in regular and manageable steps.  If you've been left behind then I strongly recommend that you start making plans for upgrading your platform, or moving to a newer one.  The effort will be well worth it when your application is still evolving and performing for many years to come!  If any other platform gave away such incredible improvements in features and performance for free, it would be big news.  Let's make it big news in PHP too.</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/TXyGmGhe4Bs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/php-version-adoption/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/php-version-adoption?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=php-version-adoption</feedburner:origLink></item>
		<item>
		<title>Simplest PHP Generator Example</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/URqxQsvd9cg/simplest-php-generator-example</link>
		<comments>http://www.lornajane.net/posts/2013/simplest-php-generator-example#comments</comments>
		<pubDate>Wed, 22 May 2013 18:30:13 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[generators]]></category>
		<category><![CDATA[php5.5]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2354</guid>
		<description><![CDATA[I really like the generators feature that's arriving in PHP 5.5, and since we're now into release candidate releases, it's actually not that far away. I've been speaking on this topic and I thought I'd share my trivially simple code &#8230; <a href="http://www.lornajane.net/posts/2013/simplest-php-generator-example">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>I really like the generators feature that's arriving in PHP 5.5, and since we're now into release candidate releases, it's actually not that far away.  I've been speaking on this topic and I thought I'd share my trivially simple code example from my slides.</p>
<h3>Writing a Generator</h3>
<p>The generators use the <code>yield</code> keyword to feed values out as they are iterated over.  In code, they really look a lot like a function (or method):</p>
<p><div class="pyg"><pre><span class="cp">&lt;?php</span>
<span class="k">function</span> <span class="nf">getValues</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// totally trivial example</span>
    <span class="nx">yield</span> <span class="s2">&quot;Apple&quot;</span><span class="p">;</span>
    <span class="nx">yield</span> <span class="s2">&quot;Ball&quot;</span><span class="p">;</span>
    <span class="nx">yield</span> <span class="s2">&quot;Cat&quot;</span><span class="p">;</span>
<span class="p">}</span>
</pre></div><br />
<span id="more-2354"></span></p>
<p>The main difference is that this "function" will retain its state and yield the next value when it is used again.</p>
<h3>Using a Generator</h3>
<p>It's not obvious from the calling code that a generator is in use - and that's a feature IMO.  Here's an example that uses the generator declared above:</p>
<p><div class="pyg"><pre><span class="cp">&lt;?php</span>
<span class="nv">$stuff</span> <span class="o">=</span> <span class="nx">getValues</span><span class="p">();</span>

<span class="k">foreach</span><span class="p">(</span><span class="nv">$stuff</span> <span class="k">as</span> <span class="nv">$thing</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">echo</span> <span class="nv">$thing</span> <span class="o">.</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">;</span>
<span class="p">}</span>
</pre></div><br />
<!--more--><br />
From this, you might assume that <code>getValues()</code> returns an iterator or array.  I can imagine refactoring applications that absolutely do expect either of those to use generators instead, so that's intentional!  If you do <code>var_dump($stuff)</code>, however, you'll see an object of type Generator.</p>
<p>Each time the <code>foreach</code> tries to fetch the next item from $stuff, the <code>getValues()</code> generator gets called, and runs until a <code>yield</code> statement causes a value to be emitted.</p>
<h3>When To Use Generators</h3>
<p>There's nothing in these examples that makes a generator a better choice than, say, returning an array, so why are generators even useful?  For the most part, they will be great for either formulaic or very large datasets.  If you wanted to perform some task on all prime numbers up to ten digits long, you could certainly generate a list and iterate over it.  However, that list could be quite large, and the generator could calculate and supply the next value on an as-needed basis.</p>
<p>The other use is for data sets which are large in comparison to the size of the memory available to PHP.  A generator could fetch data in a loop, or read incrementally from a stream, and only have that one piece of data hanging around in PHP's memory at any one time.</p>
<h3>Looking Forward to Generators</h3>
<p>Generators are just one more in a long string of understated features coming in to the newer versions of PHP, but it's one that will make your data-heavy applications run light and quick - I can't thank the PHP core team enough for bringing us this feature!</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/URqxQsvd9cg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/simplest-php-generator-example/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/simplest-php-generator-example?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simplest-php-generator-example</feedburner:origLink></item>
		<item>
		<title>Setting Multiple Headers in a PHP Stream Context</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/dZT8G9uzNXs/setting-multiple-headers-in-a-php-stream-context</link>
		<comments>http://www.lornajane.net/posts/2013/setting-multiple-headers-in-a-php-stream-context#comments</comments>
		<pubDate>Tue, 07 May 2013 07:35:22 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[streams]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2344</guid>
		<description><![CDATA[Last week I tried to create a PHP stream context which set multiple headers; an Authorization header and a Content-Type header. All the examples I could find showed headers built up as a string with newlines added manually, which seemed &#8230; <a href="http://www.lornajane.net/posts/2013/setting-multiple-headers-in-a-php-stream-context">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>Last week I tried to create a PHP stream context which set multiple headers; an Authorization header and a Content-Type header.  All the examples I could find showed headers built up as a string with newlines added manually, which seemed pretty clunky and not-streams-like to me.</p>
<p>In fact, you've been able to pass this as an array since PHP 5.2.10, so to set multiple headers in the stream context, I just used this:</p>
<div class="pyg"><pre><span class="cp">&lt;?php</span>
<span class="nv">$options</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;http&quot;</span> <span class="o">=&gt;</span> <span class="p">[</span>
    <span class="s2">&quot;method&quot;</span> <span class="o">=&gt;</span> <span class="s2">&quot;POST&quot;</span><span class="p">,</span>
    <span class="s2">&quot;header&quot;</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="s2">&quot;Authorization: token &quot;</span> <span class="o">.</span> <span class="nv">$access_token</span><span class="p">,</span>
        <span class="s2">&quot;Content-Type: application/json&quot;</span><span class="p">],</span>
    <span class="s2">&quot;content&quot;</span> <span class="o">=&gt;</span> <span class="nv">$data</span>
    <span class="p">]];</span>
<span class="nv">$context</span> <span class="o">=</span> <span class="nb">stream_context_create</span><span class="p">(</span><span class="nv">$options</span><span class="p">);</span>
</pre></div>
<p>The <code>$access_token</code> had been set elsewhere (in fact I usually put credentials in a separate file and exclude it from source control in an effort not to spread my access credentials further than I mean to!), and <code>$data</code> is already encoded as JSON.  For completeness, you can make the POST request like this:</p>
<div class="pyg"><pre><span class="cp">&lt;?php</span>
<span class="c1">// make the request</span>
<span class="nv">$response</span> <span class="o">=</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="k">false</span><span class="p">,</span> <span class="nv">$context</span><span class="p">);</span>
</pre></div>
<p>Hopefully this will help someone else doing the same thing next time (or at least I know I can come back here when I can't remember!), the array approach seems more elegant and maintainable to me.</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/dZT8G9uzNXs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/setting-multiple-headers-in-a-php-stream-context/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/setting-multiple-headers-in-a-php-stream-context?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=setting-multiple-headers-in-a-php-stream-context</feedburner:origLink></item>
		<item>
		<title>What Goes in Source Control?</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/6_Pi82BryzQ/what-goes-in-source-control</link>
		<comments>http://www.lornajane.net/posts/2013/what-goes-in-source-control#comments</comments>
		<pubDate>Mon, 29 Apr 2013 15:28:17 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[source control]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2331</guid>
		<description><![CDATA[Short answer: everything! However we need some good directory structures and source control configuration to make that a really practical answer, so this article is a quick outline of my usual advice for a good source control structure for a &#8230; <a href="http://www.lornajane.net/posts/2013/what-goes-in-source-control">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>Short answer: everything!  However we need some good directory structures and source control configuration to make that a really practical answer, so this article is a quick outline of my usual advice for a good source control structure for a standard web project.  The examples are for a PHP project but I'm sure you could apply this to your own language of choice, also. <span id="more-2331"></span></p>
<h3>Web Root</h3>
<p>The web root of your project is never the same thing as the root of your source control folder.  Typically I recommend an <code>src</code> directory for all code, then a subdirectory called something like <code>public</code> which will be your web root.  The web root contains only the entry point for your application's endpoints, typically an <code>index.php</code> file plus any assets such as javascript, images and css that you want to serve.</p>
<h3>Library Code</h3>
<p>This may or may not form part of your repository.  If it does, it should go in a source folder such as the <code>src</code> example I gave above.  You may chose to bring the code in from its own repository, using source control features like submodules in git or externals in SVN.  Alternatively, you may consider that the libraries are a platform dependency, place them on each server where they are needed, and either symlink to them or include them as appropriate.  This is particularly useful where you have several sites building on the same shared libraries; just put them in a shared place.</p>
<h3>Build Scripts</h3>
<p>Using a tool like phing or ant to repeatably perform tasks within your project is an excellent practice as it can really help to make sure things are done quickly and correctly every time.  Any project which takes advantage of these types of tools should include the configuration files (e.g. <code>build.xml</code> for phing).  These should live separate from any application code, perhaps in a <code>tools</code> directory, or even in the root of the project.</p>
<h3>Configuration</h3>
<p>Configuration might be different for every platform that an application runs on, but we still need a template to start from when we work with configuration.  To achieve this, create files called something like <code>config.php.dist</code> which contain example settings that are needed for the config (for bonus points, make these settings correct for the live platform, so that if you ever get this wrong, this platform is fastest to fix!).  Every installation will need to copy the file and call it something like <code>config.php</code> - this should then be <em>ignored</em> by your source control tools so that any changes to it, on any platform, are not shared.</p>
<p>For systems with automated deployments, it can be useful to keep the config file(s) separately on the server, and at deploy time insert a symlink at the point that the application expects the config file to be.</p>
<h3>Auxilliary Tools</h3>
<p>Many applications have extra tools around them, for example I have an open source project that has a command-line tool for trying out the API, and a tool that generates sample data you can use with the application.  Both of these are integral to the project and should be kept in the repository - perhaps each inside their own directory.</p>
<h3>Database Patches</h3>
<p>Most applications will have some way of keeping track of changes to the structure of their databases, and these are as much part of the project changes as the code is!  There are tools to help with database changes, and I wrote a post about database patching strategies myself, but either way they usually result in both patch files, and files to manage the patches.  Both of these should be in a <code>database</code> directory or similar, as part of the repo.</p>
<h3>Tests</h3>
<p>Tests are definitely part of your project, so keep those in the repo!  This ties in nicely with the comments about phing files, which can be a great way to make it easy for people to run the various test suites that you have.  Whether your project uses traditional PHPUnit testing, has functional or behavioural testing, API testing, or all of the above - check all those tests into the repository so that everyone can keep the versions up to date and run them easily.</p>
<h3>Everything and the Kitchen Sink</h3>
<p>Anything you need for your project belongs in the repo, it's not unusual to also have documentation as well as everything mentioned above, plus several other things I've probably forgotten - so add a comment to tell me what you store in your repo that I didn't mention?</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/6_Pi82BryzQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/what-goes-in-source-control/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/what-goes-in-source-control?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=what-goes-in-source-control</feedburner:origLink></item>
		<item>
		<title>The Mathematics of Recruitment and Training</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/KpnhaUz6ShA/the-mathematics-of-recruitment-and-training</link>
		<comments>http://www.lornajane.net/posts/2013/the-mathematics-of-recruitment-and-training#comments</comments>
		<pubDate>Mon, 22 Apr 2013 08:51:23 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[work]]></category>
		<category><![CDATA[economics]]></category>
		<category><![CDATA[professional development]]></category>
		<category><![CDATA[recruitment]]></category>
		<category><![CDATA[training]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2321</guid>
		<description><![CDATA[The PHP jobs market is hot, very many people find it hard to recruit the skilled staff that they need to achieve the goals of their organisation. I meet a wide variety of organisations in this technology space, and they &#8230; <a href="http://www.lornajane.net/posts/2013/the-mathematics-of-recruitment-and-training">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>The PHP jobs market is hot, very many people find it hard to recruit the skilled staff that they need to achieve the goals of their organisation.  I meet a wide variety of organisations in this technology space, and they all tell me the same story: it's really difficult to get good, qualified people.  And I believe that this is true, I know plenty of developers too and although I'll usually try to put people in touch where it makes sense to do so, it's not as if there is a great reservoir of hidden PHP talent somewhere.</p>
<p>This isn't a rant about salaries, the skills of new graduates, or the trials of dealing with recruiters, although each of those is worth a post in itself.  It's about the mathematics of providing your organisation with the talent it needs at the time that it needs it. <span id="more-2321"></span></p>
<h3>Shaping the Perfect Recruit</h3>
<p>Sometimes, you just can't get the staff.  Or rather, you can, but at >25% more salary than your organisation can really pay.  Now you have three choices:</p>
<ul>
<li>Get someone not-really-qualified and turn out not-really-excellent work</li>
<li>Get someone not-really-qualified, and then spend yet more money on getting them more qualified</li>
<li>Get someone qualified, and absorb the costs</li>
</ul>
<p>Let's put some numbers on those options, looking around it seems like a junior PHP developer in my area earns something between 18k and 24k (GBP).  If you can employ someone not qualified on 18k whom we'll call Charlie, or someone qualified on 24k whom we'll call Alex, and we assume that they stay with the organisation for three years and get a 3% pay rise every year then your costs over those three years become:</p>
<p>Charlie: £55636.20<br />
Alex: £74181.60</p>
<p>Both employees gain much from working in your organisation from three years, but Alex is still worth more than Charlie at the end of the time.<br />
<a href="http://www.lornajane.net/services/training-topics" title="Training Topics"></a><br />
Now consider a third way.  You still employ Charlie on 18k, but you set aside an additional annual budget for training and professional development, in this example this is a thousand pounds pear year.  It's not a lot, but with a bit of luck this should cover a decent training course, more than a handful books, and maybe a relevant local event too.  The total cost over three years:</p>
<p>Charlie++: £58636.20</p>
<p>At the end of three years, for very little (financial) input, you've got a much improved junior employee, ready to take on a much more senior role - although you might want to pay them a bit more in order to stop them jumping ship for another job now they have more skills!  As a direct comparison, the three options look something like this:</p>
<p><a href="http://www.lornajane.net/wp-content/uploads/2013/04/graph.png"><img src="http://www.lornajane.net/wp-content/uploads/2013/04/graph.png" alt="Three options for recruitment and training" width="551" height="310" class="alignnone size-full wp-image-2327" /></a></p>
<p>On a very personal note, the jobs I've stayed in the longest are the ones where I was promoted internally (officially, or where I was trusted with more challenging tasks) and in web development, the churn of employees is much higher than it is in other places.  By investing in your employees and persuading them to stay, the business continues to reap the benefits of the investment, rather than continuously investing in lining the pockets of recruiters.  Getting the right staff does cost money, but whether you direct that money into your business or outside of it is up to you.</p>
<p><i>(This isn't the point of the article, I think these ideas apply to businesses everywhere, but if you'd like to check out my <a href="http://www.lornajane.net/services/training-topics" title="Training Topics">training pages</a>, then you may)</i></p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/KpnhaUz6ShA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/the-mathematics-of-recruitment-and-training/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/the-mathematics-of-recruitment-and-training?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=the-mathematics-of-recruitment-and-training</feedburner:origLink></item>
		<item>
		<title>Pretty-Printing JSON with Python's JSON Tool</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/7AuKs6vOwjU/pretty-printing-json-with-pythons-json-tool</link>
		<comments>http://www.lornajane.net/posts/2013/pretty-printing-json-with-pythons-json-tool#comments</comments>
		<pubDate>Mon, 15 Apr 2013 12:55:25 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2317</guid>
		<description><![CDATA[Today's quick tip is something that was widely retweeted after my "Debugging HTTP" talk at the ever-fabulous WhiskyWeb conference last weekend. When working with JSON on the commandline, here's a quick tip for showing the JSON in a nicer format: &#8230; <a href="http://www.lornajane.net/posts/2013/pretty-printing-json-with-pythons-json-tool">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>Today's quick tip is something that was widely retweeted after my "Debugging HTTP" talk at the ever-fabulous WhiskyWeb conference last weekend.  When working with JSON on the commandline, here's a quick tip for showing the JSON in a nicer format:</p>
<div class="pyg"><pre>curl http://api.joind.in | python -mjson.tool
</pre></div>
<p>You need python installed, but the JSON extension is probably included, and that's all you need for this tool.  The result is something like:</p>
<p><a href="http://www.lornajane.net/wp-content/uploads/2013/04/python-mjsontool.png"><img src="http://www.lornajane.net/wp-content/uploads/2013/04/python-mjsontool-300x202.png" alt="python-mjsontool" width="300" height="202" class="alignnone size-medium wp-image-2318" /></a></p>
<p>You can also use this approach to present JSON data that has been captured to another file, for example, it's a handy trick that I use often when developing something with JSON as a data format.</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/7AuKs6vOwjU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/pretty-printing-json-with-pythons-json-tool/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/pretty-printing-json-with-pythons-json-tool?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pretty-printing-json-with-pythons-json-tool</feedburner:origLink></item>
		<item>
		<title>Video Course on Learnable: OOP PHP</title>
		<link>http://feedproxy.google.com/~r/lornajane/~3/WXeHWiBmkG4/video-course-on-learnable-oop-php</link>
		<comments>http://www.lornajane.net/posts/2013/video-course-on-learnable-oop-php#comments</comments>
		<pubDate>Thu, 28 Mar 2013 13:41:09 +0000</pubDate>
		<dc:creator>lornajane</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[learnable]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[sitepoint]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://www.lornajane.net/?p=2296</guid>
		<description><![CDATA[I'm delighted to announce that my new video course on Object-Oriented PHP is now available on Learnable! It's very much an introduction, aiming to cover WHY objects are so cool as well as how to declare and use one. The &#8230; <a href="http://www.lornajane.net/posts/2013/video-course-on-learnable-oop-php">Continue reading <span class="meta-nav">&#8594;</span></a><p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
]]></description>
				<content:encoded><![CDATA[<p>I'm delighted to announce that my new video course on Object-Oriented PHP is now <a href="https://learnable.com/courses/object-oriented-php-2734" target="_blank">available on Learnable</a>!  It's very much an introduction, aiming to cover WHY objects are so cool as well as how to declare and use one.  The course is a mix of video (filmed in my kitchen, welcome to my home everyone!), screencast, a couple of exercises for you to try, and also plenty of sample code to download.  If you are just looking to get started with OOP, or know someone who is, then hopefully this will help you out.</p>
<p>On a related note, I'm also doing a Sitepoint "Talk with the Experts" session on 11th April (early morning UK time, as a special treat for everyone in Europe and further east, that doesn't happen often!).  There are more details here: <a href="http://www.sitepoint.com/forums/showthread.php?1012242-Talk-Object-oriented-PHP-with-the-Experts">http://www.sitepoint.com/forums/showthread.php?1012242-Talk-Object-oriented-PHP-with-the-Experts</a> and I hope you can join me then.</p>
<p>Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only).  This post was originally published at <a href="http://www.lornajane.net">LornaJane</a></p>
<img src="http://feeds.feedburner.com/~r/lornajane/~4/WXeHWiBmkG4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lornajane.net/posts/2013/video-course-on-learnable-oop-php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lornajane.net/posts/2013/video-course-on-learnable-oop-php?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=video-course-on-learnable-oop-php</feedburner:origLink></item>
	</channel>
</rss>
