<?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>@ fake&#039;s &#187; Code</title>
	<atom:link href="http://plind.dk/category/development/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://plind.dk</link>
	<description>customized rants from a PHP dev&#039;s viewpoint</description>
	<lastBuildDate>Wed, 11 Aug 2010 12:52:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Dependency injection and Zend Framework</title>
		<link>http://plind.dk/2010/08/11/dependency-injection-and-zend-framework/</link>
		<comments>http://plind.dk/2010/08/11/dependency-injection-and-zend-framework/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 12:52:33 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[DI]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[ZF]]></category>

		<guid isPermaLink="false">http://plind.dk/?p=419</guid>
		<description><![CDATA[Lately I&#8217;ve been working on a site based on the Zend Framework. It&#8217;s been a good chance to get more intimate with ZF, learning the inner workings and quirks of the framework. Today I came across the question of how to do dependency injection for your controllers &#8211; I was looking for a way to [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been working on a site based on the Zend Framework. It&#8217;s been a good chance to get more intimate with ZF, learning the inner workings and quirks of the framework. Today I came across the question of how to do dependency injection for your controllers &#8211; I was looking for a way to rid the code of the &#8216;new&#8217; keyword as well as static methods, coupling things more loosely.</p>
<p>Controllers aren&#8217;t meant to override the __construct() method in ZF &#8211; sure you can do it, but there are meant to be better ways. That leads to the question: how? Well, if you do have a look at the __construct() method of Zend_Controller_Action, you&#8217;ll notice that it takes three parameters. The last one is the interesting one here: it&#8217;s an array called invokeArgs. This should immediately set you off testing what gets passed in &#8211; a bunch of goodies, it turns out. Among other things, you&#8217;ll be getting a copy of the Bootstrap object.</p>
<h2>ZF Controller Dependency Injection, #1</h2>
<p>The above leads to the first, not too good way of injecting things. Just stick whatever you want injected into the bootstrap object &#8211; your controller has access to that through the invokeArgs parameter. That&#8217;s not a very good solution though, as you&#8217;ll be breaking <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">the Law of Demeter</a>: your controller needs to know that your injected param sits inside the bootstrap element, so you&#8217;ll be accessing the injected elemented indirectly. Not nice.</p>
<h2>ZF Controller Dependency Injection, #2</h2>
<p>I googled a bit and came across <a href="http://www.ibuildings.co.uk/blog/archives/1181-Dependency-Injection-and-Zend-Framework-Controllers.html">Dependency Injection and Zend Framework Controllers</a>, which has a nice solution to the problem. As the param name suggests, invokeArgs can be modified &#8211; you can add to the args to your heart&#8217;s content. You need to use the setParam() method of Zend_Controller_Front &#8211; so, in the bootstrap object for instance, you can do the following:</p>
<pre>$front = Zend_Controller_Front::getInstance();
$front-&gt;setParam('factory', new MyFactory);</pre>
<p>Your object will then get passed to the controller in the invokeArgs array. You can access this either through $this-&gt;_invokeArgs['factory'] or the getInvokeArg() method of Zend_Controller_Action &#8211; the latter being preferable.</p>
]]></content:encoded>
			<wfw:commentRss>http://plind.dk/2010/08/11/dependency-injection-and-zend-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sorting algorithms: Heap sort</title>
		<link>http://plind.dk/2010/05/23/sorting-algorithms-heap-sort/</link>
		<comments>http://plind.dk/2010/05/23/sorting-algorithms-heap-sort/#comments</comments>
		<pubDate>Sun, 23 May 2010 16:09:30 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[algorithms]]></category>
		<category><![CDATA[heapsort]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sorting algorithms]]></category>

		<guid isPermaLink="false">http://plind.dk/?p=161</guid>
		<description><![CDATA[It&#8217;s been a while since I did the last post (merge sort) in my sorting algorithms in PHP series (new readers start with Sorting algorithms: bubblesort) so I thought it about time that I add the next part. This time I&#8217;m going for heap sort. This algorithm has some similarities with merge sort, mainly the [...]]]></description>
			<content:encoded><![CDATA[<div class='series_toc'><h3>Series: Sorting Algorithms</h3><ol><li><a href='http://plind.dk/2009/11/06/sorting-algorithms-bubblesort/' title='Sorting algorithms: bubblesort'>Sorting algorithms: bubblesort</a></li><li><a href='http://plind.dk/2009/11/07/sorting-algorithms-quick-update/' title='Sorting algorithms: quick update'>Sorting algorithms: quick update</a></li><li><a href='http://plind.dk/2009/11/16/sorting-algorithms-insertion-sort/' title='Sorting algorithms: Insertion Sort'>Sorting algorithms: Insertion Sort</a></li><li><a href='http://plind.dk/2009/11/30/sorting-algorithms-shell-sort/' title='Sorting algorithms: Shell sort'>Sorting algorithms: Shell sort</a></li><li><a href='http://plind.dk/2010/01/07/sorting-algorithms-selection-sort/' title='Sorting algorithms: Selection sort'>Sorting algorithms: Selection sort</a></li><li><a href='http://plind.dk/2010/01/10/sorting-algorithms-merge-sort/' title='Sorting algorithms: Merge sort'>Sorting algorithms: Merge sort</a></li><li>Sorting algorithms: Heap sort</li></ol></div> <p>It&#8217;s been a while since I did the last post (<a href="http://plind.dk/2010/01/10/sorting-algorithms-merge-sort/">merge sort</a>) in my sorting algorithms in PHP series (new readers start with <a href="http://plind.dk/2009/11/06/sorting-algorithms-bubblesort/">Sorting algorithms: bubblesort</a>) so I thought it about time that I add the next part. This time I&#8217;m going for <a href="http://en.wikipedia.org/wiki/Heapsort">heap sort</a>. This algorithm has some similarities with merge sort, mainly the recursive nature, the divide and conquer idea: heap sort treats an array like a tree of elements instead of just one big pool of elements. Other than that, like some of the other sort algorithms presented it can be sorted in place, leading to less memory use &#8211; however it is not a stable sort, as the elements can quite easily change order.</p>
<p>In details, heap sort works by imposing a hierarchical tree structure on the set of elements and that the structure satisfies the heap requirement: that any given node be of equal to or less value than it&#8217;s parent. This is actually only a requirement for one type of heaps, the max-heaps &#8211; the other type, min-heaps, work in the opposite way, namely by having a parent node be always equal to or less than a child node. The reason this is significant is that you will always know which element is the largest: it&#8217;s the root node (in a max-heap, still). Hence, if we have a heap in proper order, we can then take the root node out of the heap and put it at the end of the array to sort. After bringing the heap in order again, we can repeat this, popping off the next largest element and putting it at the second to last position in the array.</p>
<p>Laying it out in steps, it looks like:</p>
<ol>
<li>heapify array</li>
<li>pop root element off and store at end of array</li>
<li>heapify remaining heap</li>
<li>repeat step 2-3 while constantly moving one step back when storing popped element</li>
</ol>
<p>And that&#8217;s it! Well, it obviously gets a bit harder once you get into the details &#8211; and without those, no sorting :) As with merge sort, it&#8217;s the recursive function that&#8217;s most important to the algorithm: the heapify thing. This is where the time will be spent so this is where it&#8217;s most important that things are optimized and that the algorithm works out.</p>
<p>So how does the heapify function work? It&#8217;s rather simple: it compares a node with it&#8217;s two leaves and if one of the is (or both are) larger than the root a swap is made &#8211; the largest leaf takes the place of the root node and vice versa. Because of the hierarchical structure of the heap, every node can have at most two leaves. If a swap is made, the heapify function recursively calls itself with the index of the swapped out leaf (the previous root, now a leaf) because this may now be a new root node in another local heap which then has to be checked. If on the other hand a swap is not made the heapify function simply returns: the heap is in order.</p>
<p>In terms of sorting, this means that you first heapify the array once and then of course once per element you pop off the array. As the algorithm swaps out the root node (the one to be popped off the heap) with the last leaf in the array the heapify function then has to be called to get the heap back into shape. Because the last element of the heap is smaller than any of it&#8217;s ancestors, the heapify function will recursively call itself a maximum of log<sub>2</sub>(n)-1 times. As the heap grows smaller, the number of recursions drops but this obviously happens on a log<sub>2</sub> scale as well so this is not a major factor in the speed &#8211; the biggest speed factor lies in a combination of the fact that sorting a heap when a new root is introduced, given that the heap has previously been heapified, only takes log<sub>2</sub>(n) moves and that the first heapification of an array is quite fast too.</p>
<p>Enough talk, now code.</p>
<h2>The Code</h2>
<pre>&lt;?php
class HeapSort extends BaseSort
{
    public function sortFunction()
    {
        $array = $this-&gt;store;
        $heap_length = count($array);
        $this-&gt;buildHeap($array, $heap_length);
        while ($heap_length)
        {
            $temp = $array[0];
            $array[0] = $array[$heap_length - 1];
            $array[$heap_length - 1] = $temp;
            $heap_length--;
            $this-&gt;heapify($array, 1, $heap_length);
        }
        $this-&gt;store = $array;
    }
    private function buildHeap(&amp;$array, $heap_length)
    {
        for ($i = floor($heap_length / 2); $i &gt; 0; $i--)
        {
            $this-&gt;heapify($array, $i, $heap_length);
        }
    }
    private function heapify(&amp;$array, $index, $heap_length)
    {
        $largest = $index;
        $comp = $array[$largest-1];
        $r = $index &lt;&lt; 1;
        $l = $r++;
        if (($l &lt;= $heap_length) &amp;&amp; ($array[$l-1] &gt; $comp))
        {
            $largest = $l;
            $comp = $array[$l-1];
        }
        if (($r &lt;= $heap_length) &amp;&amp; ($array[$r-1] &gt; $comp))
        {
            $largest = $r;
            $comp = $array[$r-1];
        }
        if ($largest != $index)
        {
            $temp = $array[$index-1];
            $array[$index-1] = $comp;
            $array[$largest-1] = $temp;
            $this-&gt;heapify($array, $largest, $heap_length);
        }
    }
}</pre>
<p>Quick walkthrough: first, the heap is built (or rather, the array is treated like a heap that&#8217;s out of order) after which the main loop is entered. Here, with each iteration, the root node is popped of the array (shifted, in PHP terms) and the heap is heapified again. The main action takes part in the heapify() method: it&#8217;s called with the heap, the index of the node to heapify and the length of the heap. The method checks the indexed node against it&#8217;s leaves and if any of them are larger than it a swap is made and the method is called recursively.</p>
<p>I&#8217;ve experimented a bit with optimizing the code and the version above is the fastest I&#8217;ve got it to. The biggest payoffs came from passing the array by reference instead of using a property of the class as well as passing the array length into functions &#8211; I hadn&#8217;t expected either to be a speed improvement but going that way shaved off 5 (five) seconds of the running time when sorting 100,000 elements. Which, I guess, leads me to the results.</p>
<h2>Results</h2>
<pre>1000 elements to sort.
Sanity check. PHP native sort() algorithm took: 0.000878 seconds. Memory used: 64360 bytes
Running Heapsort sort. Algorithm took: 0.089941 seconds. Memory used: 64360 bytes</pre>
<p>At 1,000 elements the algorithm it&#8217;s running in about 1.25 times the time of the merge sort implementation I made.</p>
<pre>10000 elements to sort.
Sanity check. PHP native sort() algorithm took: 0.012138 seconds. Memory used: 665804 bytes
Running Heapsort sort. Algorithm took: 1.208370 seconds. Memory used: 665800 bytes</pre>
<p>At 10,000 elements it&#8217;s running in 1.5 times the merge sort &#8211; pretty good but not quite the same.</p>
<pre>100000 elements to sort.
Sanity check. PHP native sort() algorithm took: 0.222491 seconds. Memory used: 6524576 bytes
Running Heapsort sort. Algorithm took: 14.997653 seconds. Memory used: 6524560 bytes</pre>
<p>With 100,000 elements the pattern is fairly clear in terms of how the algorithm is doing &#8211; a bit less than a straight O(n log n). Final test is 1,000,000 elements.</p>
<pre>1000000 elements to sort.
Sanity check. PHP native sort() algorithm took: 3.602368 seconds. Memory used: 64194572 bytes
Running Heapsort sort. Algorithm took: 188.843620 seconds. Memory used: 64194576 bytes</pre>
<p>Increasing the number of elements to sort by an order of magnitude increases the run time by 12.5 &#8211; which is pretty good (compare to the internal PHP algorithm which increases by a factor 15).</p>
 <div class='series_links'><a href='http://plind.dk/2010/01/10/sorting-algorithms-merge-sort/' title='Sorting algorithms: Merge sort'>Previous in series</a> </div>]]></content:encoded>
			<wfw:commentRss>http://plind.dk/2010/05/23/sorting-algorithms-heap-sort/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Awesome Command-fu</title>
		<link>http://plind.dk/2010/04/29/awesome-command-fu/</link>
		<comments>http://plind.dk/2010/04/29/awesome-command-fu/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 11:10:34 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[command-fu]]></category>
		<category><![CDATA[man]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://plind.dk/?p=368</guid>
		<description><![CDATA[A good friend of mine mentioned that SSH supports escape sequences &#8211; something I had never thought of. Or rather, something I had wished for every time I&#8217;d been faced with a dead SSH connection. Turns out, you can easily close any SSH connection (dead or alive) by issuing the following sequence: &#60;CR&#62;~. The CR [...]]]></description>
			<content:encoded><![CDATA[<p>A good friend of mine mentioned that SSH supports escape sequences &#8211; something I had never thought of. Or rather, something I had wished for every time I&#8217;d been faced with a dead SSH connection. Turns out, you can easily close any SSH connection (dead or alive) by issuing the following sequence:</p>
<pre>&lt;CR&gt;~.</pre>
<p>The CR in there is a carriage return, i.e. pressing the enter key to create a new line. One caveat though: the ~ is the default escape character for SSH but it can be changed (or removed) so you need to make sure you&#8217;re using the proper escape character when issuing escape sequences &#8211; otherwise, no fun/profit.</p>
<p>Closing an SSH connection is not the only thing you can do: you can also suspend an SSH connection by doing</p>
<pre>&lt;CR&gt;~^Z</pre>
<p>where ^Z is &lt;ctrl&gt;+z. But wait, there&#8217;s more! You can also change the SSH connection you&#8217;re in to add or remove port forwards, by opening a command line:</p>
<pre>&lt;CR&gt;~C</pre>
<p>And a personal favourite: if you&#8217;re using several SSH connections in serial, you can forward an escape sequence by adding another ~ after the first. Closing connection #2 then becomes:</p>
<pre>&lt;CR&gt;~~.</pre>
<p>And in the same fashion, suspending the second connection becomes:</p>
<pre>&lt;CR&gt;~~^Z</pre>
<p>This, dear reader, is <strong>awesome!</strong> There&#8217;s just no end to the fun :)</p>
<p>The moral: read your man pages (so much good stuff hidden away in there)!</p>
]]></content:encoded>
			<wfw:commentRss>http://plind.dk/2010/04/29/awesome-command-fu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.htaccess voodoo</title>
		<link>http://plind.dk/2010/04/08/htaccess-voodoo/</link>
		<comments>http://plind.dk/2010/04/08/htaccess-voodoo/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 23:16:06 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[URL rewriting]]></category>

		<guid isPermaLink="false">http://plind.dk/?p=353</guid>
		<description><![CDATA[Every once in a while I have to do some .htaccess rewriting and every time I end up deeply fascinated at the possibilities that it offers. This time round the situation was as follows: for a client we had done some advanced search functionality, which uses fairly detailed URLs to store the search (the search [...]]]></description>
			<content:encoded><![CDATA[<p>Every once in a while I have to do some <a title="Wikipedia on .htaccess" href="http://en.wikipedia.org/wiki/.htaccess">.htaccess</a> rewriting and every time I end up deeply fascinated at the possibilities that it offers. This time round the situation was as follows: for a client we had done some advanced search functionality, which uses fairly detailed URLs to store the search (the search is parsed into an abstract syntax tree, then serialized to a URL). The problem now was that we had rewritten the serialized syntax &#8230; and somehow a famous search engine had picked up on the URLs and was getting bad results from them. What to do?</p>
<p>The solution was URL rewriting using .htaccess. However, it wasn&#8217;t straight forward URL rewriting &#8211; the serialized search was encoded in the query string, and that was the only part that needed a rewrite. How does the Apache Rewrite module handle this? Very well, it turns out.</p>
<h2>Solution &#8211; part 1</h2>
<p>The first thing to realise is that <a title="RewriteRule specs" href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html#RewriteRule">RewriteRules</a> by themselves won&#8217;t do any good &#8211; they only work on the base part of the URL, ignoring the query string. This means you have to turn to the second part of the rewrite: the <a title="RewriteCond specs" href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html#RewriteCond">RewriteCond</a>. Now, this presented the first part of my eye-opening experience: RewriteCond allows for using regexes. This means you can do the following:</p>
<pre>RewriteCond %{QUERY_STRING} ^id=([0-9]+)
</pre>
<p>And you&#8217;ll match on query strings that start with id = some number of digits. You can use pretty much any extended regular expression you desire &#8230; which makes it very powerful!</p>
<h2>Solution &#8211; part 2</h2>
<p>As you can probably guess from the above code bit, you can also use capturing groups in the RewriteCond regexes. Not only that, though: you can reference these captured groups in a RewriteRule. It&#8217;s done slightly different from capture reference in RewriteRule regexes (these are done using $) in that a reference to a captured group from a RewriteCond uses a % as prefix. Hence, you can do:</p>
<pre>RewriteCond %{QUERY_STRING} ^id=([0-9]+)
RewriteRule ^product.php /product/%1? [R=301,L]
</pre>
<p>And you&#8217;ll be redirecting product.php?id=123 to product/123 using a 301. Notice the ? at the end of the rewritten URL &#8211; it&#8217;s there to make sure ModRewrite doesn&#8217;t append the original query string.</p>
<p>At this point, my woes were almost over &#8211; there was just one obstacle left.</p>
<h2>Solution &#8211; part 3</h2>
<p>When the Rewrite module does redirects, it normally also escapes characters in the URL, that could otherwise turn out problematic. One such character is %. However, this escaping is itself very problematic upon redirects, because any url_encode()d URL will contain lots of % characters followed by a character code. When ModRewrite is done with the URL, it&#8217;ll have substituted all %2F with %252F, for instance &#8230; not what you want.</p>
<p>There&#8217;s a very simple solution to this, though: you can set a flag to stop the Rewrite module from doing any escaping. What you do is:</p>
<pre>RewriteCond %{QUERY_STRING} ^id=([0-9]+)
RewriteRule ^product.php /product/%1? [R=301,L,NE]
</pre>
<p>This stops ModRewrite from escaping the URL, leaving you with whatever was in the original.</p>
<p>Using the above bits and pieces you can rewrite a URL like</p>
<pre>/search?blah=hum%20dinger%20and%what%20not%3Aliteral
</pre>
<p>to</p>
<pre>/search?q=hum%20dinger%20and%what%20not%3Aliteral&amp;rewritten=true
</pre>
<p>It&#8217;s voodoo for sure, but damned cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://plind.dk/2010/04/08/htaccess-voodoo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Geonames library</title>
		<link>http://plind.dk/2010/03/22/geonames-library-2/</link>
		<comments>http://plind.dk/2010/03/22/geonames-library-2/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 23:47:05 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Geonames]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[PHP library]]></category>

		<guid isPermaLink="false">http://plind.dk/?p=348</guid>
		<description><![CDATA[A couple of days I was doing some work on BeWelcome, updating some code to fetch geo data from Geonames.org. Our old code had been using a mixture of a spaf maps class and php functions and trying to get it to work properly seemed to demand quite a bit of tinkering &#8211; plus, there [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of days I was doing some work on <a href="http://www.bewelcome.org/">BeWelcome</a>, updating some code to fetch geo data from <a href="http://www.geonames.org">Geonames.org</a>. Our old code had been using a mixture of a spaf maps class and php functions and trying to get it to work properly seemed to demand quite a bit of tinkering &#8211; plus, there was the chance I might break something. I then had a look at the Geonames site and there are quite a few different libraries for querying Geonames &#8211; but nothing in plain PHP. However, looking at the documentation of their API it didn&#8217;t seem like it would be very hard to knock something up &#8211; so that&#8217;s what I did.</p>
<p>After about 2 hours of coding, I had some very basic classes that provide the most useful functionality of Geonames (useful for BeWelcome anyway): doing a fulltext wildcard search, fetching details for one specific location, and fetching hierarchies of locations. The library provides some static functions for generating location objects, and these location objects can then in turn be worked with using some of the same methods that the library provides (such as getting child locations or parent locations).</p>
<p>The usage is currently extremely simple &#8211; some examples:</p>
<pre>// searching for a location
$results = GeoNamesService::search($searchterm, $rowcount /* optional, defaults to 100 */);

// fetching parent hierarchy for a location
$hierarchy = GeoNamesService::hierarchy($id);

// getting the parent of an existing GeoNamesObject
$parent = $geo_object-&gt;getParent();</pre>
<p>As you can probably guess, the main reasoning was taking out the boilerplate code and removing the stuff we just didn&#8217;t use. As a consequence, this library doesn&#8217;t currently offer that much extra functionality. This will be built in later though, so you&#8217;re able to use some of the options when searching, for instance. Also, a number of the other ways of interacting with Geonames are worth looking at, like finding a location by postcode.</p>
<p>After I had spent a bit of time on the project and got it to a working basic (including some unit-tests), I figured I&#8217;d breathe some life into it and so I put it on GitHub &#8211; so anyone can take it and use it if they have a need for it. It&#8217;s available here: <a href="http://github.com/Fake51/GeoNames-Library">PHP Geonames Library</a> and the license is a GPL v.3 so you can just grab and use in any OS project as you see fit.</p>
]]></content:encoded>
			<wfw:commentRss>http://plind.dk/2010/03/22/geonames-library-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
