<?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>Open Source Web Thoughts &#187; php</title>
	<atom:link href="http://blog.dewaldbotha.co.za/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.dewaldbotha.co.za</link>
	<description></description>
	<lastBuildDate>Fri, 25 Nov 2011 09:17:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Test drive your PHP code</title>
		<link>http://blog.dewaldbotha.co.za/2009/03/30/test-drive-your-php-code/</link>
		<comments>http://blog.dewaldbotha.co.za/2009/03/30/test-drive-your-php-code/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 14:53:14 +0000</pubDate>
		<dc:creator>dewaldbotha</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[test driven development]]></category>
		<category><![CDATA[unit testing]]></category>
		<category><![CDATA[martin fowler]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[uml]]></category>

		<guid isPermaLink="false">http://blog.dewaldbotha.co.za/2009-03-30/test-drive-your-php-code/</guid>
		<description><![CDATA[Lately I&#8217;ve ventured fully submerged into the world of Test driven development (TDD). This might start out a bit scary, especially if you have only heard about it, but never done it yourself. There is a couple of good reads on the net, so you might want to start out by familiarising yourself with this <a href="http://blog.dewaldbotha.co.za/2009/03/30/test-drive-your-php-code/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve ventured fully submerged into the world of <a href="http://en.wikipedia.org/wiki/Test-driven_development" title="Test Driven Development">Test driven development (TDD)</a>.</p>
<p>This might start out a bit scary, especially if you have only heard about it, but never done  it yourself.  There is a couple of good reads on the net, so you might want to start out by familiarising yourself with this exciting way of doing things.</p>
<p>Have a look at <a href="http://en.wikipedia.org/wiki/Test-driven_development" title="Test Driven Development" target="_blank">http://en.wikipedia.org/wiki/Test-driven_development</a> or <a href="http://lmgtfy.com/?q=test+driven+development" title="Test Driven Development" target="_blank">Google it</a>.</p>
<h3>What is test driven development?</h3>
<p><a href="http://en.wikipedia.org/wiki/Test-driven_development" title="Test Driven Development">Test driven development (TDD)</a> is more a change in coding philosophy than anything else.   Some of us might say: &#8220;&#8230;yip, I&#8217;ve written a couple of unit tests when I had some spare time at the end of my project.&#8221;</p>
<p>To be honest, this is a bit of the wrong way round method of doing things, kind of like building a house by putting on the roof first.   I think <a href="http://martinfowler.com/" title="Martin Fowler" target="_blank">Martin Fowler</a> describes it best when he pointed out these three components.</p>
<ul>
<li>Write a test for the next bit of functionality you want to add.</li>
<li>Write the functional code until the test passes.</li>
<li>Refactor both new and old code to make it well structured.</li>
</ul>
<p><a href="http://en.wikipedia.org/wiki/Test-driven_development" title="Test Driven Development" target="_blank">TDD</a> is a branch of <a href="http://en.wikipedia.org/wiki/Agile_software_development" title="Agile Development" target="_blank">Agile development</a> which was based upon the first stages of <a href="http://en.wikipedia.org/wiki/Extreme_programming" title="Extreme Programming" target="_blank">extreme programming</a>, but has really become a coding methodology that changed the way in which a lot of projects are being done.<br />
<span id="more-17"></span></p>
<h3>What do I need to get started?</h3>
<h4>UML</h4>
<p>It is always good to have a basic <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">Unified Modeling Language (UML)</a> diagram of how you would like your objects/classes to work and behave, but believe me, after you analyzed it through testing, you would do a fair amount of refactoring.</p>
<p>Here we have some pretty <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> for a very basic Message object which must create and delete messages.  The Message implements a Message_Store object for message storage.</p>
<p><img src="http://farm4.static.flickr.com/3451/3397964953_6165f47f15.jpg" alt="Message UML" /></p>
<h4>PHPUnit</h4>
<p>Now before you even attempt to write a line of code &#8211; go to <a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">http://www.phpunit.de/</a>.</p>
<p>This will become your friend in days/months/years to come and you will learn to love it.  <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>Background:</strong></p>
<p><a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">PHPUnit</a> was created by a German fellow called <a href="http://sebastian-bergmann.de/" title="Sebastian Bergmann" target="_blank">Sebastian Bergmann</a> and has grown into a full fledge PHP testing framework.  It was based upon <a href="http://en.wikipedia.org/wiki/SUnit" title="SUnit" target="_blank">SUnit</a>, which was developed by the father of <a href="http://en.wikipedia.org/wiki/Extreme_programming" title="Extreme Programming" target="_blank">extreme programming</a>, <a href="http://en.wikipedia.org/wiki/Kent_Beck" title="Kent Beck" target="_blank">Kent Beck</a>,  to accommodate testing in <a href="http://en.wikipedia.org/wiki/Smalltalk" title="Smalltalk" target="_blank">Smalltalk</a>.</p>
<p><strong>Installing:</strong></p>
<p>The easiest way to install <a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">PHPUnit</a> would be via your <a href="http://pear.php.net/" title="Pear" target="_blank">PEAR</a> Installer.</p>
<p>First you must register <a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">PHPUnit</a> <a href="http://pear.php.net/" title="Pear" target="_blank">PEAR</a> channel with your local <a href="http://pear.php.net/" title="Pear" target="_blank">PEAR</a> environment.</p>
<pre lang="php">
pear channel-discover pear.phpunit.de</pre>
<p>Now you can install <a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">PHPUnit</a> to your local <a href="http://pear.php.net/" title="Pear" target="_blank">PEAR</a> packages</p>
<pre lang="php">
pear install phpunit/PHPUnit</pre>
<p>That should be it for now &#8211; <a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">PHPUnit</a> should hopefully be installed on your system.  According to the <a href="http://www.phpunit.de/" title="PHPUnit" target="_blank">PHPUnit</a> website the directory it is located in is /usr/lib/php/PHPUnit, but I instead found it inside /usr/share/php/PHPUnit on my Ubuntu installation.  In all likelyhood it should be located inside the same directory as your <a href="http://pear.php.net/" title="Pear" target="_blank">PEAR</a> installation.</p>
<h3>Let the testing commence.</h3>
<p>&#8220;Whoa, whoa, whoa!&#8221;, most developers would cry.  &#8220;How can you possibly test code you haven&#8217;t written yet?&#8221;, they all sing together.</p>
<p>Here is where the mind shift starts.  You should have a basic understanding of how your code should work/behave after you have done the <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> for your class.   So why not use the way you think your code should behave in your tests.</p>
<h4>Your test class</h4>
<p>First things first.  If you have a look at your <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> diagram you would see that there is a dependency between the Message class and Message_Store class.</p>
<p><img src="http://farm4.static.flickr.com/3451/3397964953_6165f47f15.jpg" alt="Message UML" /></p>
<p>You should now write the test for how your Message object should behave.</p>
<pre lang="php">
//Include the base class for PHPUnit in order for your tests to work
require_once 'PHPUnit/Framework/TestCase.php';

//Include the Message class you are testing
require_once 'Message.php';

//Your Message Test Class
class MessageTest extends PHPUnit_Framework_TestCase
{

//Create a private class variable for re-use
private $oMessage;

/*
The setUp class function is native to PHPUnit and is executed infront of each
test function.  This will help you do things such as create a new object to work with before each new test.
*/
protected function setUp()
{
    $this->oMessage = new Message();
}

/*
The tearDown class function is reverse of the setUp() function and is executed after each test.
This will help you do things such as setting objects to a NULL value for re-use.
*/
protected function tearDown()
{
  $this->oMessage = null;
}

/*
First you test the construction of your Message object.
This isn't really necessary, since you know that a PHP constructor is suppose to work <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , but is just done
for completeness sake.
$this->assertType() tests to see if the object you created is of the type 'Message'.
*/
public function testMessageConstructed()
{
    $this->assertType('Message', new Message());
}

/*
Now you start testing all the public methods inside your class.  Since you are going to test the way you want
your code to work in, you will only be allowed to test the public accessible methods.  The tests will still cover any
private methods which is called from the public method tested.
This is kind of a double-barrel test. Since you can prove that the setStore is working if the getStore returns the
correct object.
$this->assertSame() will test if two different variables are of the exact same type
*/
public function testSetAndGetStore()
{
    $oPDO = new PDO('mysql:host=localhost;dbname=localdb', 'username', 'password');
    $oMessageStore = new Message_Store_Pdo($oPDO);
    $this->oMessage->setStore($oMessageStore);
    $this->assertSame($oMessageStore,$this->oMessage->getStore());
}

/*
You will now test if the save function will return a variable of bool type, either true if correctly saved or
false if incorrectly saved
*/
public function testSave()
{
    $oPDO = new PDO('mysql:host=localhost;dbname=localdb', 'username', 'password');
    $oMessageStore = new Message_Store_Pdo($oPDO);
    $this->oMessage->setStore($oMessageStore);
    $this->assertType('boolean',$this->oMessage->save('Hello'));
}

/*
You will now test if the delete function will return a variable of bool type, either true if deleted or
false if not deleted.
*/
public function testDelete()
{
    $oPDO = new PDO('mysql:host=localhost;dbname=localdb', 'username', 'password');
    $oMessageStore = new Message_Store_Pdo($oPDO);
    $this->oMessage->setStore($oMessageStore);
    $this->assertType('boolean',$this->oMessage->delete(1));
}

}</pre>
<h4>What does our test class tell us?</h4>
<p>That&#8217;s it &#8211; we now have a couple of basic tests to cover our Message class.  The important thing about writing tests is that you should cover all public functions used in the class you are testing.  At the moment these tests shouldn&#8217;t run, but it will give you a clear idea of where to start and is great for debugging whilst writing code.</p>
<p>Already there is a bit of a discrepancy of what is happening in the unit tests and <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a>.  The way we test our code, is the way we would like our objects to behave.  In the <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> we assumed that the the message store could be part of the message object, but as our tests showed us &#8211; there might be a more elegant way using a storage object, which would allow for more pluggable, <a href="http://en.wikipedia.org/wiki/Loosely_coupled" title="Loosely coupled" target="_blank">loosely-coupled</a> code.</p>
<p>If we passed a storage object into the Message object itself, after a while the message object will become bloated and unusable, since now you have to cater for your different storage objects within the Message object.  For e.g. create a saveToFileSystem function and a saveToDatabase function, where some functions might become redundant when using a specific storage object.</p>
<p>So instead of passing a PDO storage object directly to the message, you could have a Message_Store object which <a href="http://php.net/interfaces" title="PHP Inteface" target="_blank">interfaces</a> to your various storage objects, such as a PDO or filesystem etc.</p>
<p>Thus turning:</p>
<pre lang="php">
$oMessage = new Message();
$oPDO = new PDO('mysql:host=localhost;dbname=localdb', 'username', 'password');
$oMessage->setStore($oPDO);</pre>
<p>Into:</p>
<pre lang="php">
$oMessage = new Message();
$oPDO = new PDO('mysql:host=localhost;dbname=localdb', 'username', 'password');
$oMessageStore = new MessageStore($oPDO);
$oMessage->setStore($oMessageStore);</pre>
<p>By creating a Message_Store class, rather than building extra code onto your Message object, you reverse any dependencies that might occur within the Message object.  All this means is that for you can now create a message object, and pass a <a href="http://php.net/interfaces" title="Interface" target="_blank">interfaced</a> storage object to it, thus allowing your code to become more flexible, without building layers of complexity itself into the Message object.</p>
<h4>Refactor your code.</h4>
<p>Now update your <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> to include an interface to the Message_Store object.</p>
<p><img src="http://farm4.static.flickr.com/3633/3367692592_1f58519ff7.jpg" alt="Message UML" /></p>
<p>Let&#8217;s build our message class according to the tests and updated <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> diagram.</p>
<pre lang="php">
class Message
{

    private $oMessageStore;

    public function __construct($oMessageStore=Null)
    {
        $this->oMessageStore = $oMessageStore;
    }

    public function setStore($oMessageStore)
    {
        $this->oMessageStore = $oMessageStore;
    }

    public function getStore()
    {
        return $this->oMessageStore;
    }

    public function save()
    {
        return $this->oMessageStore->create($this);
    }

    public function delete($sMessageId)
    {
        return $this->oMessageStore->delete($sMessageId);
    }

}</pre>
<p>Now your Message class is starting to look elegant.  Now you can create the interface.</p>
<pre lang="php">
interface Message_Store_Interface
{
public function __construct($oStorage);
public function create($oMessage);
public function delete($sMessageId);
}</pre>
<p>You can now implement the interface in the various Message store objects.</p>
<pre lang="php">
class Message_Store_Pdo implements Message_Store_Interface{

    private $oPdo;

    public function __construct($oPdo)
    {
        $this->oPdo = $oPdo;
    }

    public function create($oMessage)
    {
        $sSql = "insert into message_store (message)
        values (?)";
        $oSql = $this->oPdo->prepare($sSql);
        $oSql->bindParam(1, $oMessage->sMessage);
        $oSql->execute();
        return (bool) $this->oPdo->lastInsertId();
    }

    public function delete($sMessageId)
    {
        $sSql = "DELETE FROM message_store
        WHERE message_id = ?";
        $oSql = $this->oPdo->prepare($sSql);
        $oSql->bindParam(1, $sMessageId);
        $oSql->execute();
        return (bool) $oSql->rowCount();
    }

}</pre>
<h3>The advantages of Test Driven Development and Unit Testing</h3>
<h4>Running the unit tests</h4>
<p>Now the big moment has arrived.  Time to run your test.  Assuming there is no syntax errors the test should execute fine.<br />
Run this by going to your command prompt and enter the following</p>
<pre lang="php">
phpunit tests/MessageTest.php</pre>
<p>If you saved the tests to MessageTest.php in the tests directory, everything should execute fine and the following would be displayed.</p>
<pre lang="php">
dewald@dewald-desktop:/var/www/mobi$ phpunit tests/MessageTest.php
PHPUnit 3.3.14 by Sebastian Bergmann.

....

Time: 0 seconds

OK (4 tests, 4 assertions)
dewald@dewald-desktop:/var/www/mobi$</pre>
<p>You have compiled your tests and ran it succesfully. <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Whoohoo &#8211; if your tests gave an error, just follow the debug messages and fix your code.  Easy as that.</p>
<p>You can also create reports to see if you have achieved acceptable code coverage by running.</p>
<pre lang="php">
phpunit --coverage-html /tmp/tests/ tests/MessageTest.php</pre>
<p>The reports should can be found in the /tmp/tests/ directory and should look something like this:</p>
<p><img src="http://farm4.static.flickr.com/3636/3398100607_9eab3051fd.jpg" alt="Test Report" /></p>
<h4>In the End</h4>
<p>In the beginning of the article I wrote that <a href="http://martinfowler.com/" title="Martin Fowler" target="_blank">Martin Fowler</a> said the following about <a href="http://en.wikipedia.org/wiki/Test-driven_development" title="Test Driven Development" target="_blank">Test Driven Development</a>:</p>
<p><strong>Write a test for the next bit of functionality you want to add.</strong></p>
<p>We wrote all our test for the functionality of our Message object in the way which we would like our object to behave.  We then test the results of that object.</p>
<p><strong>Write the functional code until the test passes.</strong></p>
<p>We wrote the functional code for the classes to make it work as we determined through our tests.</p>
<p><strong>Refactor both new and old code to make it well structured.</strong></p>
<p>After writing the tests, we realised that our code has some short-comings and dependencies, which we could reverse in-time, since we saw the way it was supposed to work in unit tests meant refactoring our <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" title="Unified Modeling Language" target="_blank">UML</a> and inherently we would have needed to refactor our code.</p>
<p><strong>What now?</strong><br />
<a href="http://en.wikipedia.org/wiki/Test-driven_development" title="Test Driven Development" target="_blank">TDD</a> doesn&#8217;t come naturally.  Especially if you were used to years of a different kinds of development techniques.  It comes through practice and experience.</p>
<p>I&#8217;ll suggest you read through the <a href="http://www.phpunit.de/manual/3.3/en/" title="PHPunit manual and examples" target="_blank">PHPUnit manual and examples</a>, as to see how flexible the testing framework can be, also as a start, write some unit tests for your old code, and you might be surprised just how efficient you could have been.  <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dewaldbotha.co.za/2009/03/30/test-drive-your-php-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>the down-low on mobile device detection</title>
		<link>http://blog.dewaldbotha.co.za/2009/02/19/the-down-low-on-mobile-device-detection/</link>
		<comments>http://blog.dewaldbotha.co.za/2009/02/19/the-down-low-on-mobile-device-detection/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 14:28:09 +0000</pubDate>
		<dc:creator>dewaldbotha</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[devicealtas]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mobile device detection]]></category>
		<category><![CDATA[php alternative cache]]></category>
		<category><![CDATA[php apc]]></category>
		<category><![CDATA[wurfl]]></category>

		<guid isPermaLink="false">http://blog.dewaldbotha.co.za/2009-02-19/the-down-low-on-mobile-device-detection/</guid>
		<description><![CDATA[so &#8211; you say you want to detect which mobile devices hit your site? &#8211; in the past, this has been a bit of an issue, but lately &#8211; with really nice projects available out there such as WURFL or DeviceAtlas, you are able to concentrate harder on other issues, instead of having to write <a href="http://blog.dewaldbotha.co.za/2009/02/19/the-down-low-on-mobile-device-detection/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>so &#8211; you say you want to detect which mobile devices hit your site? &#8211; in the past, this has been a bit of an issue, but lately &#8211; with really nice projects available out there such as <a href="http://wurfl.sourceforge.net/" title="WURFL" target="_blank">WURFL</a> or <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a>, you are able to concentrate harder on other issues, instead of having to write a complete library of your own.</p>
<p>so for this, i&#8217;ve decided on <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a>.  just head on over to <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a> and open a developers account &#8211; you will get a one year developer&#8217;s license to play around to see how cool it is.</p>
<p>after registering &#8211; click on the <a href="http://deviceatlas.com/downloads" title="download DeviceAtlas" target="_blank">downloads</a> link &#8211; then go to the php example and download the source files.  after de-tar-and-un-zipping the file, just extract the contents.  at the moment all we are really interested in, is the <em><strong>Mobi/Mtld/DA </strong></em>directory and its contents &#8211; also create a <em><strong>json</strong></em> directory and drop the <em><strong>Sample.jso</strong></em>n file inside.</p>
<p>dump everything into a web directory somewhere. <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><span id="more-16"></span>create a <em><strong>deviceatlas.php</strong></em> file in the working directory root and put the following inside.</p>
<pre lang="php">//includes the DeviceAtlas API

include 'Mobi/Mtld/DA/Api.php';//fetch the previously populated apc cache instance into a variable

$tree = apc_fetch('tree');

//Get the properties from a variable containing a JSON tree loaded from cache

$properties = Mobi_Mtld_DA_Api::getProperties($tree, $_SERVER['HTTP_USER_AGENT']);

//Output the phone properties for your viewing pleasure

print_r($properties);</pre>
<p>&#8216;hhmmm, that&#8217;s it?&#8217;, you might ask, and if you were clever you would have noticed something strange in the code above.</p>
<p>yip, that is pretty much it &#8211; but you also need caching.  the <em><strong>apc_fetch(&#8216;tree&#8217;)</strong></em> command in the code above actually fetches the json file already dumped into a &#8216;tree&#8217; cache instance in <a href="http://www.php.net/manual/en/intro.apc.php" title="PHP APC Cache" target="_blank">PHP APC</a> (Alternative PHP Cache).</p>
<p>why <a href="http://www.php.net/manual/en/intro.apc.php" title="PHP APC Cache" target="_blank">PHP APC</a>, you may also ask.  well, besides using the overstated <a href="http://www.danga.com/memcached/" title="Memcached" target="_blank">memcached</a> (<a href="http://www.phpbuilder.com/board/archive/index.php/t-10346692.html" title="Memcache vs APC" target="_blank">you might want to read this</a>), there are some methods to the madness.  with <a href="http://www.php.net/manual/en/intro.apc.php" title="PHP APC Cache" target="_blank">PHP APC</a>, the cache is shared on a server.  it might not be accessible from other servers, but this is not really a con in my mind.</p>
<p>if you wish to scale your application later one and add another server, there is going to be some issues, you might say &#8211; but there will also be issues if you have millions of users hit one central instance of <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a>.  so, having one instance of <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a> per server might not be too much of an issue.  also when it comes to updating the json file, you might want to consider the <a href="http://en.wikipedia.org/wiki/Single_point_of_failure" title="Single Point of Failure" target="_blank">single point of failure</a> issue of just having one server.</p>
<p>so have a couple of servers, and just write some scripts to update the single instances of <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a>, rather than updating one, already busy server which still needs a cache update.</p>
<p>but, back to business.</p>
<p>first you have to install <a href="http://www.php.net/manual/en/intro.apc.php" title="PHP APC Cache" target="_blank">PHP APC</a>.  i found <a href="http://www.howtoforge.com/apc-php5-apache2-debian-etch" title="Apc Installation guide" target="_blank">this handy guide</a> on the net, which helped me install it on my <a href="http://en.wikipedia.org/wiki/Debian" title="Debian" target="_blank">debian</a> system and integrate it with <a href="http://en.wikipedia.org/wiki/Apache_server" title="Apache" target="_blank">apache</a> and <a href="http://en.wikipedia.org/wiki/Php5" title="PHP 5" target="_blank">php5</a> &#8211; there is also a guide at the bottom for <a href="http://en.wikipedia.org/wiki/Red_hat" title="Red Hat" target="_blank">fedora</a> based machines, so don&#8217;t fret my <a href="http://en.wikipedia.org/wiki/Linux" title="Linux" target="_blank">linux</a> loving friends <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>you can create a php script to run the following &#8211; which should cache your <a href="http://deviceatlas.com/" title="DeviceAtlas" target="_blank">DeviceAtlas</a> tree into <a href="http://www.php.net/manual/en/intro.apc.php" title="PHP APC Cache" target="_blank">PHP APC</a>.</p>
<pre lang="php">//ads the sample json data from DeviceAtlas

apc_add('tree', Mobi_Mtld_DA_Api::getTreeFromFile("json/Sample.json"));</pre>
<p>from the first code example, the output might look something like this (depending on your phone)</p>
<p>Array<br />
(<br />
[wmv] =&gt; 0<br />
[vendor] =&gt; Nokia<br />
[mobileDevice] =&gt; 1<br />
[memoryLimitMarkup] =&gt; 357000<br />
[memoryLimitDownload] =&gt; 61440<br />
[midiMonophonic] =&gt; 1<br />
[midiPolyphonic] =&gt; 1<br />
[mpeg4] =&gt; 1<br />
[3gpp] =&gt; 1<br />
[drmOmaForwardLock] =&gt; 1<br />
[drmOmaCombinedDelivery] =&gt; 1<br />
[drmOmaSeparateDelivery] =&gt; 1<br />
[markup.xhtmlMp10] =&gt; 1<br />
[markup.xhtmlBasic10] =&gt; 1<br />
[image.Jpg] =&gt; 1<br />
[image.Png] =&gt; 1<br />
[amr] =&gt; 1<br />
[mp3] =&gt; 1<br />
[aac] =&gt; 1<br />
[h263Type0InVideo] =&gt; 1<br />
[gprs] =&gt; 1<br />
[edge] =&gt; 1<br />
[image.Gif87] =&gt; 1<br />
[uriSchemeTel] =&gt; 0<br />
[qcelp] =&gt; 0<br />
[hsdpa] =&gt; 0<br />
[amrInVideo] =&gt; 1<br />
[3gpp2] =&gt; 0<br />
[displayColorDepth] =&gt; 18<br />
[model] =&gt; N70<br />
[https] =&gt; 1<br />
[image.Gif89a] =&gt; 0<br />
[umts] =&gt; 0<br />
[displayWidth] =&gt; 176<br />
[displayHeight] =&gt; 208<br />
[markup.xhtmlMp11] =&gt; 0<br />
[markup.xhtmlMp12] =&gt; 0<br />
[csd] =&gt; 0<br />
[hscsd] =&gt; 0<br />
[id] =&gt; 204255<br />
[_matched] =&gt; NokiaN70<br />
[_unmatched] =&gt; -1/5.0609.2.0.1 Series60/2.8 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0<br />
)</p>
<p><a href="http://deviceatlas.com/properties" title="DeviceAtlas properties" target="_blank">you can view the attribute explanations here </a></p>
<p>now you can use the phone&#8217;s specific properties to your advantage.  you also might want to look at the <a href="https://addons.mozilla.org/en-US/firefox/addon/59" title="User agent switcher" target="_blank">user agent switcher add-on</a> for firefox for testing purposes.</p>
<p>that&#8217;s it.  now every once in a while you can just update the json file, delete the current cache (<a href="http://www.php.net/manual/en/function.apc-delete.php" title="APC Delete Cache" target="_blank">http://www.php.net/manual/en/function.apc-delete.php</a>) and bob&#8217;s your device detecting, apc caching uncle.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dewaldbotha.co.za/2009/02/19/the-down-low-on-mobile-device-detection/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>game theory pattern code example</title>
		<link>http://blog.dewaldbotha.co.za/2009/02/17/game-theory-pattern-code-example/</link>
		<comments>http://blog.dewaldbotha.co.za/2009/02/17/game-theory-pattern-code-example/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 08:50:50 +0000</pubDate>
		<dc:creator>dewaldbotha</dc:creator>
				<category><![CDATA[design patterns]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[game theory]]></category>

		<guid isPermaLink="false">http://blog.dewaldbotha.co.za/2009-02-17/game-theory-pattern-code-example/</guid>
		<description><![CDATA[so i finally took the time to write some code to better articulate my thoughts on &#8216;game theory pattern&#8217;. /* * Abstract Unifier class to select objects from different sources. */ abstract class childObjectUnifier { protected $currentObjectLocation; public function __construct() { $this->currentObjectLocation = get_class($this); } public function getData() { switch ($this->currentObjectLocation) { case 'currentServerLoginObject': return <a href="http://blog.dewaldbotha.co.za/2009/02/17/game-theory-pattern-code-example/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>so i finally took the time to write some code to better articulate my thoughts on &#8216;game theory pattern&#8217;.</p>
<pre lang="php">
/*
* Abstract Unifier class to select objects from different sources.
*/

abstract class childObjectUnifier
{
    protected $currentObjectLocation;

    public function __construct()
    {
        $this->currentObjectLocation = get_class($this);
    }

    public function getData()
    {
        switch ($this->currentObjectLocation)
        {
             case 'currentServerLoginObject':
                    return $this->currentServerLoginFunction();
                    break;

             case 'remoteServerLoginObject':
                    return $this->remoteServerLoginFunction();
                    break;

             default:
                    die('Current user load not available');
        }
    }
}

/*
* Login Object which exists on the current server.
* This object could still be hit on the current server if the current user load is not high.
* Better utilizes the current server.
*/

class currentServerLoginObject extends childObjectUnifier
{
    public function currentServerLoginFunction()
    {
         return 'Some function on the current server';
    }
}

/*
* This login object could exist remotely, for e.g. a restfull/soap/xml-rpc service
* which could be hit if the current server load is climbing.
* Could possibly use a dedicated 'login' server if user load is exceedingly high on current machine.
*/

class remoteServerLoginObject extends childObjectUnifier
{
    public function remoteServerLoginFunction()
    {
        return 'Some function on the remote server';
    }
}

/*
* The game theory pattern which decides which objects to instantiate based on logical
* decisions made by solid data.
* In this example the current user load.
*/

class GameTheoryPattern
{
    public $currentObject;

    function __construct($iCurrentUserLoad)
    {
        $this->currentObject = $this->baseObjectUponStrategicData($iCurrentUserLoad);
    }

    private function baseObjectUponStrategicData($iCurrentUserLoad)
    {
         switch ($iCurrentUserLoad)
         {
             case $iCurrentUserLoad < 1000:
                    return new currentServerLoginObject();
                    break;

             case $iCurrentUserLoad >= 1000 :
                    return new remoteServerLoginObject();
                    break;

             default:
                    die('Current user load not available');
        }
    }
}

//GetCurrentUserLoad
$iCurrentUserLoad = 1000;

//Create Login Object based on the Game Theory Pattern
$oLogin = new GameTheoryPattern($iCurrentUserLoad);

//Call an function from the unifier class
echo $oLogin->currentObject->getData();

?></pre>
<p>It should be pretty self explanatory &#8211; due to the high level comments <img src='http://blog.dewaldbotha.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>feel free to add suggestions or comments &#8211; since i&#8217;m pretty sure there could be a better way, but for now, just to convey the message it should be sufficient.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dewaldbotha.co.za/2009/02/17/game-theory-pattern-code-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>crossing the mvc divide, kohana and zend style</title>
		<link>http://blog.dewaldbotha.co.za/2009/01/23/crossing-the-mvc-divide-kohana-and-zend-style/</link>
		<comments>http://blog.dewaldbotha.co.za/2009/01/23/crossing-the-mvc-divide-kohana-and-zend-style/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 09:36:40 +0000</pubDate>
		<dc:creator>dewaldbotha</dc:creator>
				<category><![CDATA[framework]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[kohanaphp]]></category>
		<category><![CDATA[model view controller]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.dewaldbotha.co.za/2009-01-23/crossing-the-mvc-divide-kohana-and-zend-style/</guid>
		<description><![CDATA[so, i&#8217;ve been pretty much a zend framework addict, ever since i coded my first bootstrap.  thinking back to that countless hours trying to understand the beast that is zf, ahhh, what fond memories&#8230;  and lately i&#8217;ve also been playing around a bit with kohana, which is another web based mvc framework, but definitely a <a href="http://blog.dewaldbotha.co.za/2009/01/23/crossing-the-mvc-divide-kohana-and-zend-style/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>so, i&#8217;ve been pretty much a <a href="http://framework.zend.com/" title="Zend Framework" target="_blank">zend framework</a> addict, ever since i coded my first bootstrap.  thinking back to that countless hours trying to understand the beast that is <a href="http://framework.zend.com/" title="Zend Framework" target="_blank">zf</a>, ahhh, what fond memories&#8230;  and lately i&#8217;ve also been playing around a bit with <a href="http://kohanaphp.com/" title="kohana" target="_blank">kohana</a>, which is another web based mvc framework, but definitely a bit more lightweight and easier to use than others.</p>
<p>there is however a bit of an issue with <a href="http://en.wikipedia.org/wiki/Model-view-controller#Implementations_of_MVC_as_web-based_frameworks" title="Web based mvc" target="_blank">web based mvc frameworks</a>, and in my opinion a large freaking elephant that no one seems to talk about.  how can i call a controller from within a view and assign an action to it &#8211; and is it correct to do so?</p>
<p>and before the quiet whispers start, i&#8217;d like to note that this does not necessarily go against <a href="http://en.wikipedia.org/wiki/Model-view-controller" title="Model View Controller" target="_blank">mvc</a> principles.  if you think about it &#8211; the whole point of <a href="http://en.wikipedia.org/wiki/Model-view-controller" title="Model View Controller" target="_blank">mvc</a> is to seperate business logic, application logic and the view (presentation logic) &#8211; and i&#8217;ve confirmed this with a couple of conversations with other developers.  but on the other hand, if you feel that i have overstepped a boundary &#8211; please do let me know if there is a better, or more correct way of doing this.</p>
<p><span id="more-11"></span><strong>now lets give a practical problem:</strong></p>
<p>i have a view template, lets call it home, which consists out of a header, navigation, content and footer.  now my content is pretty much controlled by the controller and whatever the view calls to display.  but say for example something you wish to partially include a login form in the top header.</p>
<p>how do i actually use a controller to change the way the view behaves, without building the logic into all the controllers which i access.  now in order to overcome this &#8211; we can attach a controller, lets call it log controller, to the view.  this controller will have the business logic to decide whether or not a login or a logout form must be generated.</p>
<p>now the obvious would be to include a partial view, but then the issue arrives where you let your view start making logic decisions, instead of presentation. on the other hand, you can use the current controller to help you decide this, but if you ask me, that might be a bit of overkill and lots of extra and duplicate coding.</p>
<h3>the solution:</h3>
<p>in <a href="http://framework.zend.com/" title="Zend Framework" target="_blank">zend framework</a>, i found the solution to be a bit easier than in <a href="http://kohanaphp.com/" title="kohana" target="_blank">kohana</a>, but still fun to figure out.</p>
<h4><img src="http://farm4.static.flickr.com/3415/3219206619_3a9927a7ca_o.jpg" alt="Zend Framework" width="429" height="255" /></h4>
<h3><a href="http://framework.zend.com/" title="Zend Framework" target="_blank">zend framework</a>:</h3>
<p>okay, so i have my home template, which is controlled by my home controller.  on my home template in my header i have a form which would change depending on if the user is logged in or not, which i would like to be controlled by my log controller.</p>
<p>so, in my view i would do the following call:<strong><code></code></strong></p>
<p><strong><code>&lt;?php echo $this-&gt;action('log','generateForm') ?&gt;</code></strong></p>
<p>which would go to the log controller and call the method generateForm() &#8211; so in generate form i will be able to decide whether the user is logged in or not and assign the corresponding result to the view assigned to the controller, in the case above it would most likely be the generateForm view.</p>
<p>there you go &#8211; without having to overcomplicate things or duplicate code, you can assign controllers as part of your presentation logic with a simple call.  i have however not yet figured out how to pass variables to the action method you are calling, but as soon as i have an update i will let you know.</p>
<h4><img src="http://farm4.static.flickr.com/3102/3219908744_e4b6f969c4_o.png" alt="Kohana" width="400" height="200" /></h4>
<h3><a href="http://kohanaphp.com/" title="kohana" target="_blank">kohana</a>:</h3>
<p>in <a href="http://kohanaphp.com/" title="kohana" target="_blank">kohana</a> the task is  a bit more complicated &#8211; luckily i found in the underbelly of the <a href="http://forum.kohanaphp.com/" title="kohana" target="_blank">kohana forums</a> an user with the same problem &#8211; which came up with the following solution -</p>
<p><strong><code>&lt;?php<br />
class Dispatch_Core{</code></strong></p>
<p><strong><code>protected $controller;</code></strong></p>
<p><strong><code> public static function controller($controller)</code><br />
<code>{</code><br />
<code>$controller_file=strtolower($controller);</code></strong></p>
<p><strong><code>// Set controller class name</code><br />
<code>$controller = ucfirst($controller).'_Controller';</code></strong></p>
<p><strong><code>if(!class_exists($controller, FALSE))</code><br />
<code>{</code><br />
<code>// If the file doesn't exist, just return</code><br />
<code>if (($filepath = Kohana::find_file('controllers', $controller_file)) === FALSE)</code><br />
<code>return FALSE;</code></strong></p>
<p><strong><code>// Include the Controller file</code><br />
<code>require_once $filepath;</code><br />
<code>}</code></strong></p>
<p><strong><code>// Run system.pre_controller</code><br />
<code>Event::run('dispatch.pre_controller');</code></strong></p>
<p><strong><code>// Initialize the controller</code><br />
<code>$controller = new $controller;</code></strong></p>
<p><strong><code>// Run system.post_controller_constructor</code><br />
<code>Event::run('dispatch.post_controller_constructor');</code></strong></p>
<p><strong><code>return new Dispatch($controller);</code><br />
<code>}</code><br />
<code>public function __construct(Controller $controller)</code><br />
<code>{</code><br />
<code>$this-&gt;controller=$controller;</code></strong></p>
<p><strong><code>}</code></strong></p>
<p><strong><code>public function __get($key)</code><br />
<code>{</code><br />
<code>if($key=='controller')</code><br />
<code>{</code><br />
<code>return $this-&gt;$key;</code><br />
<code>}</code><br />
<code>else</code><br />
<code>{</code><br />
<code>return $this-&gt;controller-&gt;$key;</code><br />
<code>}</code><br />
<code>}</code></strong></p>
<p><strong><code>public function __set($key,$value)</code><br />
<code>{</code><br />
<code>$this-&gt;controller-&gt;$key=$value;</code><br />
<code>}</code></strong></p>
<p><strong><code>public function __toString()</code><br />
<code>{</code><br />
<code>return $this-&gt;render();</code><br />
<code>}</code></strong></p>
<p><strong><code>public function render()</code><br />
<code>{</code><br />
<code>return (string) $this-&gt;controller;</code><br />
<code>}</code></strong></p>
<p><strong><code>public function __call($name,$arguments=null)</code><br />
<code>{</code><br />
<code>if(method_exists($this-&gt;controller,$name))</code><br />
<code>{</code><br />
<code>return $this-&gt;method($name,$arguments);</code><br />
<code>}</code><br />
<code>return false;</code><br />
<code>}</code></strong></p>
<p><strong><code>public function method($method,$arguments=null)</code><br />
<code>{</code><br />
<code>if(!method_exists($this-&gt;controller,$method))</code><br />
<code>return false;</code></strong></p>
<p><strong><code>if (method_exists($this-&gt;controller,'_remap'))</code><br />
<code>{</code><br />
<code>// Make the arguments routed</code><br />
<code>$arguments = array($method, $arguments);</code></strong></p>
<p><strong><code>// The method becomes part of the arguments</code><br />
<code>array_unshift($arguments, $method);</code></strong></p>
<p><strong><code>// Set the method to _remap</code><br />
<code>$method = '_remap';</code><br />
<code>}</code></strong></p>
<p><strong><code>ob_start();</code></strong></p>
<p><strong><code>if(is_string($arguments))</code><br />
<code>{</code><br />
<code>$arguments=array($arguments);</code><br />
<code>}</code></strong></p>
<p><strong><code>switch(count($arguments))</code><br />
<code>{</code><br />
<code>case 1:</code><br />
<code>$result=$this-&gt;controller-&gt;$method($arguments[0]);</code><br />
<code>break;</code><br />
<code>case 2:</code><br />
<code>$result=$this-&gt;controller-&gt;$method($arguments[0], $arguments[1]);</code><br />
<code>break;</code><br />
<code>case 3:</code><br />
<code>$result=$this-&gt;controller-&gt;$method($arguments[0], $arguments[1], $arguments[2]);</code><br />
<code>break;</code><br />
<code>case 4:</code><br />
<code>$result=$this-&gt;controller-&gt;$method($arguments[0], $arguments[1], $arguments[2], $arguments[3]);</code><br />
<code>break;</code><br />
<code>default:</code><br />
<code>// Resort to using call_user_func_array for many segments</code><br />
<code>$result=call_user_func_array(array($this-&gt;controller, $method), $arguments);</code><br />
<code>break;</code><br />
<code>}</code></strong></p>
<p><strong><code>// Run system.post_controller</code><br />
<code>Event::run('dispatch.post_controller');</code></strong></p>
<p><strong><code>if($result!=NULL)</code><br />
<code>{</code><br />
<code>$result=ob_get_contents();</code></strong></p>
<p><strong><code>ob_end_clean();</code><br />
<code>}</code></strong></p>
<p><strong><code>return $result;</code><br />
<code>}</code></strong></p>
<p><strong><code>}</code></strong></p>
<p>now the above you can save under your library directory in your application for ease of use as something like dispatch.php.</p>
<p>so to solve the problem of the login form &#8211; in my default home template i&#8217;ve added <strong><code>&lt;?php echo $this-&gt;template-&gt;partial = new View('log/generateform');?&gt;</code></strong></p>
<p>in the generateform view i called i will use the following:</p>
<p><strong><code>&lt;?php</code><br />
<code>//call the log controller</code><br />
<code>$dispatch = Dispatch::Controller('log');</code><br />
<code>//call the generateForm method</code><br />
<code>$dispatch-&gt;method('generateForm');</code><br />
<code>//return the result from the template to the view</code><br />
<code>echo $dispatch-&gt;template;</code><br />
<code>?&gt;</code></strong></p>
<p>the above will call the  log controller and the method generateForm, in the controller, you can specify the template, for e.g. <strong><code>&lt;?php public $template = 'kohana/partial/navigation';?&gt;</code></strong> and then in the action / controller assign any values to be used by the template view/presentation.</p>
<p>oh, and one more cool thing with the above is that you can also call the method using parameters for e.g. <strong><code>&lt;?php $dispatch-&gt;generateForm(array('title'='login'));?&gt;</code></strong></p>
<h3>recap</h3>
<p>as i said in the beginning, if anyone feels that i&#8217;ve overstepped the <a href="http://en.wikipedia.org/wiki/Model-view-controller" title="Model View Controller" target="_blank">mvc</a> divide, please let me know, i&#8217;m sure that with the assigning of a controller/action from within a view is totally acceptable, since only your presentation logic is affected by it really, and the controller still decides on what is available for the view to pull, without having adjust your controllers to cater for everything.</p>
<p>and if someone knows of a quicker method in <a href="http://kohanaphp.com/" title="kohana" target="_blank">kohana</a>, also do let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dewaldbotha.co.za/2009/01/23/crossing-the-mvc-divide-kohana-and-zend-style/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

