<?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>The Developer Day &#187; PHP</title>
	<atom:link href="http://www.thedeveloperday.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thedeveloperday.com</link>
	<description>Staying Curious</description>
	<lastBuildDate>Fri, 03 Feb 2012 12:03:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Dumping Memcache Keys</title>
		<link>http://www.thedeveloperday.com/dumping-memcache-keys/</link>
		<comments>http://www.thedeveloperday.com/dumping-memcache-keys/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 21:25:16 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[memcache]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=746</guid>
		<description><![CDATA[Sometimes it&#8217;s useful to be able to quickly peek what keys memcache is storing and how old are they. A good use case for example could be to check whether something is cached or not or that they expire as they should. At first I found a way to dump memcache keys through telnet. However [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it&#8217;s useful to be able to quickly peek what keys memcache is storing and how old are they. A good use case for example could be to check whether something is cached or not or that they expire as they should.</p>
<p>At first I found a way to <a href="http://www.darkcoding.net/software/memcached-list-all-keys/" title="memcache keys telnet" target="_blank">dump memcache keys through telnet</a>. However if a memcache instance is fairly large and has a lot of slabs and thousands of keys it becomes impractical to do it manually.</p>
<p>I wrote a simple utility that helps me find keys across all memcache slabs.</p>
<pre name="code" class="php:nogutter">
#!/usr/bin/php
< ?php
$host = "127.0.0.1";
$port = 11211;
$lookupKey = "";
$limit = 10000;

$time = time();

foreach ($argv as $key => $arg) {
    switch ($arg) {
        case '-h':
            $host = $argv[$key + 1];
            break;
        case '-p':
            $port = $argv[$key + 1];
            break;
        case '-s':
            $lookupKey = $argv[$key + 1];
            break;
        case '-l':
            $limit = $argv[$key + 1];
    }
}

$memcache = memcache_connect($host, $port);

$list = array();
$allSlabs = $memcache->getExtendedStats('slabs');
$items = $memcache->getExtendedStats('items');

foreach ($allSlabs as $server => $slabs) {
    foreach ($slabs as $slabId => $slabMeta) {
        if (!is_numeric($slabId)) {
            continue;
        }

        $cdump = $memcache->getExtendedStats('cachedump', (int)$slabId, $limit);

        foreach ($cdump as $server => $entries) {
            if (!$entries) {
                continue;
            }

            foreach($entries as $eName => $eData) {
                $list[$eName] = array(
                    'key' => $eName,
                    'slabId' => $slabId,
                    'size' => $eData[0],
                    'age' => $eData[1]
                );
            }
        }
    }
}

ksort($list);

if (!empty($lookupKey)) {
     echo "Searching for keys that contain: '{$lookupKey}'\n";
     foreach ($list as $row) {
        if (strpos($row['key'], $lookupKey) !== FALSE) {
            echo "Key: {$row['key']}, size: {$row['size']}b, age: ", ($time - $row['age']), "s, slab id: {$row['slabId']}\n";
        }
     }
} else {
    echo "Printing out all keys\n";
    foreach ($list as $row) {
        echo "Key: {$row['key']}, size: {$row['size']}b, age: ", ($time - $row['age']), "s, slab id: {$row['slabId']}\n";
    }
}
</pre>
<p>This script accepts 4 parameters:</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
-h host<br />
-p port<br />
-s partial search string<br />
-l a limit of how many keys to dump from a single slab (default 10,000)
</p></blockquote>
<p>The easiest way to use it:</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
./membrowser.php -s uk<br />
Searching for keys that contain: &#8216;uk&#8217;<br />
Key: 1_uk_xml, size: 3178b, age: 1728s, slab id: 17<br />
Key: 2_uk_xml, size: 3178b, age: 1725s, slab id: 17<br />
Key: 3_uk_xml, size: 3178b, age: 1721s, slab id: 17
</p></blockquote>
<p>Download <a href="http://www.thedeveloperday.com/uploads/membrowser.phps">memcache keys dump script</a>.</p>
<p>P.S some of the code I&#8217;ve copied from <a href="http://100days.de/serendipity/archives/55-Dumping-MemcacheD-Content-Keys-with-PHP.html" target="_blank">100days.de blog post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/dumping-memcache-keys/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHPUnit email integration testing using Sendmail</title>
		<link>http://www.thedeveloperday.com/phpunit-email-integration-testing-using-sendmai/</link>
		<comments>http://www.thedeveloperday.com/phpunit-email-integration-testing-using-sendmai/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 20:54:01 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[mail testing integration functional phpunit]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=614</guid>
		<description><![CDATA[One of the problems when doing functional or integration testing is testing that emails are being sent out with a correct header and body. One such scenario could be a controller action which sends a password reset confirmation email and redirects to another action. A common way to solve such a problem is to configure [...]]]></description>
			<content:encoded><![CDATA[<p>One of the problems when doing functional or integration testing is testing that emails are being sent out with a correct header and body. One such scenario could be a controller action which sends a password reset confirmation email and redirects to another action.</p>
<p>A common way to solve such a problem is to configure the local MTA to store the test emails on the file system. The following shows how this could be done using sendmail. First create a sendmail alias by editing a file located at /etc/mail/aliases and adding a line bellow other aliases:</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
test-mail:        &#8220;| cat > /tmp/test-mail&#8221;
</p></blockquote>
<p>This tells sendmail that all incoming emails to test-mail will be written (not appended) to /tmp/test-mail. Sendmail needs to be restarted for the changes to take effect.</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
sudo /etc/init.d/sendmail restart
</p></blockquote>
<p>Depending on the situation it may be necessary to add the user who is going to be reading emails (for example apache) to the mail group.</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
sudo /usr/sbin/usermod -G mail apache
</p></blockquote>
<p>Now using PHP it should be possible to do this:</p>
<pre name="code" class="php:nogutter">
$ok = mail('test-mail', 'Hello world!', 'I am an email.');
var_dump($ok);
echo file_get_contents('/tmp/test-mail');
</pre>
<p>Further PHPUnit could be extended to add the following method to the base test case class:</p>
<pre name="code" class="php:nogutter">
public function assertEmail($attributes, $emailFilePath,
$message = '', $delta = 0, $maxDepth = 10,
$canonicalizeEol = FALSE, $ignoreCase = FALSE)
{
    $mailParser = new Company_Product_MailParser;
    $mailData = $mailParser->parseFile($emailFilePath);

    foreach ($attributes as $attribute => $value) {
        $constraint = new PHPUnit_Framework_Constraint_IsEqual(
            $mailData[$attribute], $delta, $maxDepth, $canonicalizeEol, $ignoreCase
        );
        $this->_test->assertThat($value, $constraint, $message);
    }

    if (is_file($emailFilePath) &#038;&#038; is_writable($emailFilePath)) {
        unlink($emailFilePath);
    }
}
</pre>
<p>The mail parser class name explains itself:</p>
<pre name="code" class="php:nogutter">
class Company_Product_MailParser
{
    public function parseFile($mailFilePath)
    {
        $emailBody = file_get_contents($mailFilePath);
        $attributes = array(
            'to' => '',
            'from' => '',
            'date' => '',
            'subject' => '',
            'body' => ''
        );

        foreach (array_keys($attributes) as $attribute) {
            if($attribute  == 'body') {
                if (preg_match("/\n\n(.*)/", $emailBody, $matches, PREG_OFFSET_CAPTURE)) {
                    $offset = $matches[1][1];
                    $attributes[$attribute] = quoted_printable_decode(substr($emailBody, $offset));
                }
            } else {
                if (preg_match("/" . ucfirst($attribute) . ": (.*)\n/", $emailBody, $matches)) {
                    $attributes[$attribute] = $matches[1];
                }
            }
        }

        return $attributes;
    }
}
</pre>
<p><strong>Important notice.</strong> Sendmail may not immediately send the email and it may take a few seconds for the file to appear. It may require you to add a sleep for a few seconds before the email file appears. If you find a way how it is possible to make sendmail send an email immediately please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/phpunit-email-integration-testing-using-sendmai/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Zend Framework Advanced Error Controller</title>
		<link>http://www.thedeveloperday.com/custom-profiler-for-live-environments/</link>
		<comments>http://www.thedeveloperday.com/custom-profiler-for-live-environments/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 01:31:58 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[testability]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/custom-profiler-for-live-environments/</guid>
		<description><![CDATA[The default Zend Framework Error Controller generated by Zend_Tool is quite simple. It displays a simple error message, sets a response status and if exception display is enabled in the current environment, an exception message, stack trace and request variables are displayed. While such a standard error controller may work well for many web applications [...]]]></description>
			<content:encoded><![CDATA[<p>The default <a href="http://framework.zend.com/">Zend Framework</a> Error Controller generated by <a href="http://framework.zend.com/manual/en/zend.tool.framework.html">Zend_Tool</a> is quite simple. It displays a simple error message, sets a response status and if exception display is enabled in the current environment, an exception message, stack trace and request variables are displayed.</p>
<p>While such a standard error controller may work well for many web applications it may not be suitable for everyone. The main disadvantage of the default <strong>error controller</strong> is that it does not notify developers of the errors that occurred and instead silently logs them. Many enterprise web applications will find this unacceptable and will try to implement their means of solving the issue. In this post I&#8217;ll try to show how a more advanced Zend Framework <strong>error controller</strong> could be implemented to help developers tackle errors quickly.</p>
<pre name="code" class="php:nogutter">
class ErrorController extends Zend_Controller_Action
{
    private $_notifier;
    private $_error;
    private $_environment;

    public function init()
    {
        parent::init();

        $bootstrap = $this->getInvokeArg('bootstrap');

        $environment = $bootstrap->getEnvironment();
        $error = $this->_getParam('error_handler');
        $mailer = new Zend_Mail();
        $session = new Zend_Session_Namespace();
        $database = $bootstrap->getResource('Database');
        $profiler = $database->getProfiler();

        $this->_notifier = new Application_Service_Notifier_Error(
            $environment,
            $error,
            $mailer,
            $session,
            $profiler,
            $_SERVER
        );

        $this->_error = $error;
        $this->_environment = $environment;
   }

    public function errorAction()
    {
        switch ($this->_error->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                $this->getResponse()->setHttpResponseCode(404);
                $this->view->message = 'Page not found';
                break;

            default:
                $this->getResponse()->setHttpResponseCode(500);
                $this->_applicationError();
                break;
        }

        // Log exception, if logger available
        if ($log = $this->_getLog()) {
            $log->crit($this->view->message, $this->_error->exception);
        }
    }

    private function _applicationError()
    {
        $fullMessage = $this->_notifier->getFullErrorMessage();
        $shortMessage = $this->_notifier->getShortErrorMessage();

        switch ($this->_environment) {
            case 'live':
                $this->view->message = $shortMessage;
                break;
            case 'test':
                $this->_helper->layout->setLayout('blank');
                $this->_helper->viewRenderer->setNoRender();

                $this->getResponse()->appendBody($shortMessage);
                break;
            default:
                $this->view->message = nl2br($fullMessage);
        }

        $this->_notifier->notify();
    }

    private function _getLog()
    {
        $bootstrap = $this->getInvokeArg('bootstrap');
        if (!$bootstrap->hasPluginResource('Log')) {
            return false;
        }
        $log = $bootstrap->getResource('Log');
        return $log;
    }
}
</pre>
<p>The modified error controller is aware of the environment it is running in. It&#8217;s likely that depending on the environment you would want to display different layouts with different information. For example while debugging Zend Controller Tests you may want to reduce the amount of HTML appearing in your terminal screen by disabling the layout while running in the test environment. You&#8217;ll also notice the Application_Service_Notifier_Error class dependency. This class is responsible for deciding whether to send an email to the developers and gathers potentially helpful information from different sources. You&#8217;ll also notice how the dependencies for the notifier are instantiated. It can be done in different ways using <strong>dependency injection</strong> frameworks, using <strong>bootstrap resources</strong> and so on. It&#8217;s up to you to decide what fits your application better.</p>
<pre name="code" class="php:nogutter">
class Application_Service_Notifier_Error
{
    protected $_environment;
    protected $_mailer;
    protected $_session;
    protected $_error;
    protected $_profiler;

    public function __construct(
        $environment,
        ArrayObject $error,
        Zend_Mail $mailer,
        Zend_Session_Namespace $session,
        Zend_Db_Profiler $profiler,
        Array $server)
    {
        $this->_environment = $environment;
        $this->_mailer = $mailer;
        $this->_error = $error;
        $this->_session = $session;
        $this->_profiler = $profiler;
        $this->_server = $server;
    }

    public function getFullErrorMessage()
    {
        $message = '';

        if (!empty($this->_server['SERVER_ADDR'])) {
            $message .= "Server IP: " . $this->_server['SERVER_ADDR'] . "\n";
        }

        if (!empty($this->_server['HTTP_USER_AGENT'])) {
            $message .= "User agent: " . $this->_server['HTTP_USER_AGENT'] . "\n";
        }

        if (!empty($this->_server['HTTP_X_REQUESTED_WITH'])) {
            $message .= "Request type: " . $this->_server['HTTP_X_REQUESTED_WITH'] . "\n";
        }

        $message .= "Server time: " . date("Y-m-d H:i:s") . "\n";
        $message .= "RequestURI: " . $this->_error->request->getRequestUri() . "\n";

        if (!empty($this->_server['HTTP_REFERER'])) {
            $message .= "Referer: " . $this->_server['HTTP_REFERER'] . "\n";
        }

        $message .= "Message: " . $this->_error->exception->getMessage() . "\n\n";
        $message .= "Trace:\n" . $this->_error->exception->getTraceAsString() . "\n\n";
        $message .= "Request data: " . var_export($this->_error->request->getParams(), true) . "\n\n";

        $it = $this->_session->getIterator();

        $message .= "Session data:\n\n";
        foreach ($it as $key => $value) {
            $message .= $key . ": " . var_export($value, true) . "\n";
        }
        $message .= "\n";

        $query = $this->_profiler->getLastQueryProfile()->getQuery();
        $queryParams = $this->_profiler->getLastQueryProfile()->getQueryParams();

        $message .= "Last database query: " . $query . "\n\n";
        $message .= "Last database query params: " . var_export($queryParams, true) . "\n\n";

        return $message;
    }

    public function getShortErrorMessage()
    {
        $message = '';

        switch ($this->_environment) {
            case 'live':
                $message .= "It seems you have just encountered an unknown issue.";
                $message .= "Our team has been notified and will deal with the problem as soon as possible.";
                break;
            default:
                $message .= "Message: " . $this->_error->exception->getMessage() . "\n\n";
                $message .= "Trace:\n" . $this->_error->exception->getTraceAsString() . "\n\n";
        }

        return $message;
    }

    public function notify()
    {
        if (!in_array($this->_environment, array('live', 'stage'))) {
            return false;
        }

        $this->_mailer->setFrom('do-not-reply@domain.com');
        $this->_mailer->setSubject("Exception on Application");
        $this->_mailer->setBodyText($this->getFullErrorMessage());
        $this->_mailer->addTo('alerts@domain.com');

        return $this->_mailer->send();
    }
}
</pre>
<p>This class provides an extensive report providing helpful details in what state the application was when an exception occurred. What&#8217;s the IP address of the server (maybe the application is distributed on many servers), what was the time, was it an AJAX request, what was user&#8217;s session data, request data.</p>
<p>One of the nice things to have is to be able to tell what was the last database query executed. This is especially useful if some dynamic database query fails or someone is trying to make an SQL injection. The easiest way to achieve this is to use a <a href="http://framework.zend.com/manual/en/zend.db.profiler.html">Zend_Db_Profiler</a>. But the default profiler consumes a lot of server resources and should not be enabled on production environments. To work around this we use a custom dummy profiler that does no profiling at all and just stores the last query information in memory.</p>
<pre name="code" class="php:nogutter">
class Application_Db_Profiler extends Zend_Db_Profiler
{
    protected $_lastQueryText;
    protected $_lastQueryType;

    public function queryStart($queryText, $queryType = null)
    {
        $this->_lastQueryText = $queryText;
        $this->_lastQueryType = $queryType;

        return null;
    }

    public function queryEnd($queryId)
    {
        return;
    }

    public function getQueryProfile($queryId)
    {
        return null;
    }

    public function getLastQueryProfile()
    {
        $queryId = parent::queryStart($this->_lastQueryText, $this->_lastQueryType);

        return parent::getLastQueryProfile();
    }
}
</pre>
<p>The <strong>custom error controller</strong> will only notify developers of errors that occur on production and stage environments to avoid spamming people with exceptions from the unstable development environment. The <em>Application_Service_Notify_Error</em> class is also highly testable. All the dependencies can be mocked, no global variables or constants are used. The class itself could be more refined by employing polymorphism instead of <em>if</em> statements but I believe it&#8217;s better to keep the example simple to make it easily understandable.</p>
<p>Depending on which version of the Zend Framework is being used the implementation for the custom error controller may be a little different, but the general idea is the same. In short the advanced error controller provides additional information such as session data, database queries, server variables and also is capable of notifying developers when errors occur on production or stage environments. Please let me know if this is helpful by providing feedback in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/custom-profiler-for-live-environments/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Avoiding Brittle Tests / Testing Output</title>
		<link>http://www.thedeveloperday.com/avoiding-brittle-tests-testing-output/</link>
		<comments>http://www.thedeveloperday.com/avoiding-brittle-tests-testing-output/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 00:22:22 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[functional]]></category>
		<category><![CDATA[unit]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=517</guid>
		<description><![CDATA[While unit tests have benefits they can also cause trouble. Having tests to catch software bugs is great but having tests that break whenever the application is at least slightly changed might not be very pleasant. The latter effect is called brittle tests. It may work well for applications which change rarely but may be [...]]]></description>
			<content:encoded><![CDATA[<p>While <strong>unit tests</strong> have benefits they can also cause trouble. Having tests to catch software bugs is great but having tests that break whenever the application is at least slightly changed might not be very pleasant. The latter effect is called <strong>brittle tests</strong>. It may work well for applications which change rarely but may be counterproductive for applications that change rapidly. <strong>Test brittleness</strong> can be caused by a variety of implementation details. This post aims to describe few of these details and explain ways how brittle tests can be avoided.</p>
<h2>Deciding how detailed the tests should be</h2>
<p>It&#8217;s important to have an at least general idea what tests should test and what should be left untested. Imagine having to <strong>functional test</strong> a web application UI displaying a form made of various input fields populated with values coming from the database. Quite a few things could be tested. Are all the values displayed? Are all radios, check boxes, drop-downs properly selected? Are validation messages displayed and are they correct? Are all labels displayed and correct? Are attached javascript events working? Can the form be submitted and is the data passed to the underlying layer? Is the confirmation message displayed?</p>
<p>The more things there are to test more likely that the tests will break not because of a bug but of a minor change. It&#8217;s important to pick only the important battles to fight. Even though it&#8217;s possible to test a lot of things it may not be practical to do so. It would certainly be possible to run a spelling checker on every displayed word but if it&#8217;s not critical to the application it may not be worthwhile to do so. For example <strong>testing javascript integration</strong> requires use of <a href="http://seleniumhq.org/">Selenium</a>. To work with continuous building it would require a <a href="http://seleniumhq.org/projects/remote-control/">Selenium RC</a> server to run all the browsers. Tests recorded by a selenium recorder may be brittle to a slightest HTML structure change unless designed very carefully. While selenium would provide the ultimate <strong>functional testing</strong> power it might be overkill for a simple web application. Decide what is critical to your application, which things are more likely to break than others and test those things only. Adapt to <strong>reoccurring software problems</strong> by adding additional tests.</p>
<h2>Testing output not implementation</h2>
<p>When developing <strong>unit tests</strong> the most effective way to test is by testing the output of method calls instead of testing the internal implementation. For example testing a simple multiplication function which multiplies <em>a</em> and <em>b</em> is straightforward. More sophisticated units which rely on other units require use of <strong>mocks</strong>. If possible it&#8217;s best to avoid testing that a mock was used or how many times a mock was called and what kind of data it was passed. Otherwise the test is tightly hooked to the internal implementation and is more likely to break when it changes. It comes to the first principle deciding how detailed a test should be. If you are fairly comfortable that the code is less likely to change or break or it&#8217;s less critical, hooking deep into the mocks might be avoided. Imagine having to test the following piece of code:</p>
<pre name="code" class="php:nogutter">
class Notifier
{
    public function __construct(Zend_Mail $mailer)
    {
        $this->_mailer = $mailer;
    }

    public function notify()
    {
        $this->_mailer->setBodyText('This is the text of the mail.');
        $this->_mailer->setFrom('somebody@example.com', 'Some Sender');
        $this->_mailer->addTo('someone@example.com', 'Some Recipient');
        $this->_mailer->setSubject('TestSubject');
        return $this->_mailer->send();
    }
}
</pre>
<p>In this case the mock is the <em>_mailer</em>. All it&#8217;s method calls could be mocked and tested against that they are called only once and are passed the correct data. In turn that would make the test more likely to break whenever this function is changed. Instead it may be enough to test that function <em>notify()</em> returns true whenever <em>send()</em> returns true. On other hand such a test might seem not sufficient enough and more hooks may be required. For example adding a test for <em>addTo()</em> function call. Or if the functionality is extremely critical an integration test could be created to test that an actual message was sent to the mail server with the correct header and body.</p>
<h2>Final Words</h2>
<p>In the end it&#8217;s a challenge of trying to find the the acceptable balance between <strong>testing application functionality</strong> and avoiding having too <strong>many brittle tests</strong>. Try to identify what&#8217;s important to your application, and test those things only, prefer <strong>testing output</strong> of method calls over hooking deeply into implementation. Let your tests work for you and not against you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/avoiding-brittle-tests-testing-output/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Anti Patterns</title>
		<link>http://www.thedeveloperday.com/php-anti-patterns/</link>
		<comments>http://www.thedeveloperday.com/php-anti-patterns/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 13:40:40 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[Patterns]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[antipatterns]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=572</guid>
		<description><![CDATA[Another talk I&#8217;ve atended at PHPUK 2010 was AntiPHPatterns by Stefan Priebsch. While design patterns are core implementation independent solutions to problems that occur over and over again which also serve as a great vocabulary, anti patterns are software patterns that are ineffective or counterproductive. In his presentation Stefan describes some of these anti patterns: 1. Constantitis. Excessive [...]]]></description>
			<content:encoded><![CDATA[<p>Another talk I&#8217;ve atended at <a href="http://www.phpconference.co.uk/">PHPUK 2010</a> was <a href="http://www.slideshare.net/spriebsch/antiphpatterns-php-uk-conference-2010">AntiPHPatterns</a> by <a href="http://priebsch.de/blog/">Stefan Priebsch</a>. While <strong>design patterns</strong> are core implementation independent solutions to problems that occur over and over again which also serve as a great vocabulary, <strong>anti patterns</strong> are software patterns that are ineffective or counterproductive. In his presentation Stefan describes some of these anti patterns:</p>
<p>1. <strong>Constantitis</strong>. Excessive use of global constants is considered to be a <strong>code smell</strong>. Global constants can be defined anywhere in the code base, there is a risk of name clashes if a constant is already defined, <strong>global constants</strong> make the code more coupled, testing gets more complicated since constants have to be known beforehand and defined explicitly which might be even more troubling if a constant has to change it&#8217;s value for another test. Since class constants are not global it&#8217;s OK to use them. Cure for constantitis is not to use global constants and instead use <strong>dependency injection</strong>.</p>
<p>2. <strong>Globalomania</strong>. Global variables share the same problems as global constants. Because <strong>global variables</strong> can be changed it makes them more dangerous than global constants since a change in one part of the codebase can affect the other without anyone noticing. Global variables can be cured by using <strong>dependency injection</strong>.</p>
<p>3. <strong>Singletonitis</strong>. Singleton is one of the most popular design patterns. It&#8217;s wide success is due to the fact that singletons by implementation are available globally in the entire application. The problem that <strong>singleton design pattern</strong> tries to solve is to prevent having multiple instances of the same class. This is rarely the problem in most applications and most singletons are being used as global variables instead. Singletons share the same problems as global constants and global variables and therefore should be avoided. Singletonitis has the same cure as constantitis and globalomania.</p>
<p>4. <strong>God classes</strong>. According to <strong>object oriented</strong> <strong>best practices</strong> classes should do one thing only and do it well. Classes should be refined and granular. One of the ways to think about this is to ask yourself what are the responsibilities of this class. In an ideal case you will be able to describe it in one sentence without any &#8220;and&#8217;s&#8221;. When classes start having too many  responsibilities they become <strong>god classes</strong>. Usually the whole application relies on one of the god classes which makes the application tight coupled and therefore more <strong>difficult to maintain</strong>. To cure god classes minimize <strong>class responsibilities</strong> so that objects know everything about themselves and little about others.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/php-anti-patterns/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Zend Framework Escaping Entities</title>
		<link>http://www.thedeveloperday.com/zend-framework-escaping-entities/</link>
		<comments>http://www.thedeveloperday.com/zend-framework-escaping-entities/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 00:41:10 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[entity]]></category>
		<category><![CDATA[escaping]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=537</guid>
		<description><![CDATA[Zend Framework has a powerful input filtering component Zend_Filter_Input. It provides an interface to define multiple filters and validators and apply them to a collection of data. By default values returned from Zend_Filter_Input are escaped for safe HTML output. An example of such functionality: $validators = array( 'id' => array( 'digits', 'allowEmpty' => true, ), [...]]]></description>
			<content:encoded><![CDATA[<p>Zend Framework has a powerful input filtering component <a href="http://framework.zend.com/manual/en/zend.filter.input.html">Zend_Filter_Input</a>. It provides an interface to define multiple filters and validators and apply them to a collection of data. By default values returned from Zend_Filter_Input are escaped for safe HTML output. An example of such functionality:</p>
<pre name="code" class="php:nogutter">
$validators = array(
    'id' => array(
        'digits',
        'allowEmpty' => true,
    ),
    'name' => array(
        'presence' => 'required',
        new Zend_Validate_StringLength(5, 255),
    ),
    'date' => array(
        'presence' => 'required',
        new Zend_Validate_Date('d/m/Y'),
    ),
);

$filters = array(
    '*'  => 'StringTrim',
);

$input = new Zend_Filter_Input($filters, $validators, $data);

if ($input->isValid()) {
    print_r($input->getEscaped());
} else {
    print_r($input->getMessages());
}
</pre>
<p>The code above validates the <em>$data</em> array by checking that the id key consists only of digits or is empty, that name is present and it&#8217;s min length is 5 and max length is 255 and that date is present and it&#8217;s format is <em>d/m/Y</em>. The StringTrim validator removes any spaces in front and at the end of all the <em>$data</em> values. If the <em>$data</em> array is valid all escaped values are outputted and if not a generated list of error messages is presented.</p>
<p>Recently I&#8217;ve ran into a small problem while using Zend_Input_Filter. According to the <strong>best security practices</strong> all data coming from the user should be escaped before being outputted to the screen. This also means data coming from a database. This requires to escape every single output statement in every view. In my opinion this adds unwanted verbosity, performance overhead and a possibility to easily miss that something was not escaped in one of the views. That is why if there is a possibility I would prefer to trust the database and not worry about the data incoming from it. It may not be a very good option if data in the database is most often presented in other documents than HTML. Since all values would need to be decoded which defeats the whole purpose. Though this is rarely the case.</p>
<p>By default Zend_Filter_Input escapes values by using the <a href="http://uk3.php.net/htmlentities">htmlentities</a> function. Which converts all applicable characters to HTML entities. This means that for example Danish language characters Æ Ø Å would be stored as &amp;AElig; &amp;Oslash; &amp;Aring; Which means that it would take 7 bytes on average to store a single letter that otherwise could be stored using 1 &#8211; 3 bytes using UTF-8 encoding support in MySQL. This could also potentially ruin collation sorting.</p>
<p>To overcome this issue a very similar function <a href="http://uk3.php.net/htmlspecialchars">htmlspecialchars</a> could be used. It escapes only a few certain characters such as &gt; &lt; &#8221; without escaping all international characters. The actual problem with Zend_Filter_Input is that it does not have an escape filter that uses htmlspecialchars. To solve the issue I&#8217;ve created a copy of HtmlEntities filter which uses htmlspecialchars function instead.</p>
<p>The filter can then be used like this:</p>
<pre name="code" class="php:nogutter">
$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setDefaultEscapeFilter(new Company_Product_Filter_HtmlSpecialChars());
</pre>
<p>Zend_Filter_Input is a great tool to ease form validation and filtering. I would be very interested to hear from you how this problem could be solved.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/zend-framework-escaping-entities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP London Conference 2010</title>
		<link>http://www.thedeveloperday.com/php-london-conference-2010/</link>
		<comments>http://www.thedeveloperday.com/php-london-conference-2010/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 15:36:57 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[london]]></category>
		<category><![CDATA[phpnw]]></category>
		<category><![CDATA[phpuk]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=538</guid>
		<description><![CDATA[I&#8217;m pleased to say that I will be attending the PHP UK conference 2010 in London. Last year I attended PHPNW 2009 which was great and I hope PHP London to be even better. It will be certainly interesting to listen to famous PHP speakers such as Stefan Priebsch, Fabien Potencier author of Symfony. The [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to say that I will be attending the <a href="http://www.phpconference.co.uk/">PHP UK conference 2010</a> in London. Last year I attended <a href="http://www.thedeveloperday.com/phpnw09-conference/">PHPNW 2009</a> which was great and I hope PHP London to be even better. It will be certainly interesting to listen to famous PHP speakers such as <a href="http://priebsch.de/">Stefan Priebsch</a>, <a href="http://fabien.potencier.org/">Fabien Potencier</a> author of Symfony. The conference schedule has been announced and these are the talks that I&#8217;m going to attend:</p>
<ul>
<li>The lost art of simplicity</li>
<li>AntiPHPatterns</li>
<li>PHP 5.3 in practice</li>
<li>PHPillow &amp; CouchDB &amp; PHP</li>
<li>&#8216;In search of&#8230;&#8217; &#8211; integrating site search systems</li>
<li>PHP on the D-BUS</li>
</ul>
<p>The keynote talk about lost art of simplicity sounds very promising. Also very eager to see Fabien&#8217;s presentation on how PHP 5.3 can be used in practice.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/php-london-conference-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Framework Database Profiler Reporting</title>
		<link>http://www.thedeveloperday.com/zend-framework-database-profiler-reporting/</link>
		<comments>http://www.thedeveloperday.com/zend-framework-database-profiler-reporting/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 19:20:24 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[profiler]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=434</guid>
		<description><![CDATA[Zend Framework has a powerful Database Profiler component. It is remarkably simple to integrate the database profiler with the Zend Framework front controller with the use of Firefox addons FireBug and FirePHP: // In your bootstrap file $profiler = new Zend_Db_Profiler_Firebug('All DB Queries'); $profiler->setEnabled(true); // Attach the profiler to your db adapter $db->setProfiler($profiler); Or just [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.zendframework.com">Zend Framework</a> has a powerful <a href="http://framework.zend.com/manual/en/zend.db.profiler.html">Database Profiler</a> component. It is remarkably simple to integrate the database profiler with the Zend Framework front controller with the use of <a href="http://www.firefox.com">Firefox</a> addons <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">FireBug</a> and <a href="http://www.firephp.org/">FirePHP</a>:</p>
<pre name="code" class="php:nogutter">// In your bootstrap file

$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);

// Attach the profiler to your db adapter
$db->setProfiler($profiler);</pre>
<p>Or just by enabling it in the database configuration:</p>
<pre name="code" class="php:nogutter">$db = array(
    'type' => 'pdo_mysql',
    'host' => 'localhost',
    'dbname' => 'dbname',
    'username' => 'username',
    'password' => 'password',
    'profiler' => array(
        'enabled' => true,
        'class' => 'Zend_Db_Profiler_Firebug',
    )
);</pre>
<p>Producing nicely formatted results:</p>
<p><a href="http://www.thedeveloperday.com/wp-content/uploads/2010/02/firebug-profiler.png"><img class="alignnone size-full wp-image-522" title="Firebug Zend Framework Db Profiler" src="http://www.thedeveloperday.com/wp-content/uploads/2010/02/firebug-profiler.png" alt="" width="550" height="201" /></a></p>
<p>Firebug profiler is great tool. But it requires to use Firefox and have FireBug and FirePHP addons installed. Not everyone in your organization may be Firefox users or have these addons installed. Another drawback is that sometimes queries may be quite big and complex. It&#8217;s not easy to analyse them in a Firebug window or to copy them to an editor that supports SQL highlighting.</p>
<p>To solve that it is possible to create a custom database profiler reporting mechanism. To output the profiler queries I&#8217;ll create a custom Zend Framework action helper:</p>
<pre name="code" class="php:nogutter">
class Company_Product_Helper_Profiler extends Zend_Controller_Action_Helper_Abstract
{
    protected $_profiler;
    protected $_view;
    protected $_config;
    protected $_db;

    public function __construct(Zend_Config $config, $db)
    {
        $this->_config = $config;
        $this->_db = $db;
    }

    public function init()
    {
        $this->_view = new Zend_View();

        parent::init();
    }

    public function postDispatch()
    {
        $this->_profiler = new Company_Product_Db_Profiler_Report($this->_db1);

        if (!$this->_isProfilerEnabled()) {
            return false;
        }

        $this->outputToScreen();
    }

    protected function _isProfilerEnabled()
    {
        if ($this->_config->environment == 'live') {
            return false;
        }

        if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) {
            return false;
        }

        $profiler = $this->getRequest()->getParam('profiler');

        if (!empty($profiler)) {
            return true;
        }

        return false;
    }

    protected function outputToScreen()
    {
        $this->_view->headLink()->appendStylesheet('/css/highlight/default.css', 'screen');

        $this->_view->headScript()->appendFile('/js/highlight.pack.js');
        $this->_view->headScript()->appendScript('
            hljs.tabReplace = \'    \';
            hljs.initHighlightingOnLoad();
        ');

        $this->getResponse()->appendBody($this->_profiler);
    }
}
</pre>
<p>The <strong>action helper</strong> uses a <strong>post dispatch hook</strong>. The post dispatch hook is called after the <strong>Zend Framework</strong> dispatcher dispatches a request. A post dispatch hook is used to ensure that all queries have been run and to integrate the profiler with the Front Controller without changing any of the controller classes.</p>
<p>Action helper profiler checks to see if any profiling information should be outputted. It checks if the current configuration environment is not production to not allow unauthorized people to use the profiler. It also checks if a request is not an AJAX request, since AJAX requests may be returning JSON data structures and any additional output can break the client which sent the request. Profiler can be enabled by adding a URL query parameter <strong>?profiler=1</strong>.</p>
<p>To highlight the SQL queries profiler uses a third party JavaScript highlighting library <a href="http://softwaremaniacs.org/soft/highlight/en/">Highlight.js</a>. On page load highlight.js finds all &lt;code&gt; nodes in the DOM structure, detects the programming or markup language type of the content inside them and highlights it.</p>
<p>The profiler action helper also uses another class to format the profiler report. The profiler report class implements an iterator interface and the __toString method allowing to use it in different ways. It could also be used to format profiler output for environments such as terminals which can&#8217;t interpret HTML.</p>
<pre name="code" class="php:nogutter">
class Company_Product_Db_Profiler_Report implements Iterator
{
    protected $_profiler;
    protected $_html = false;
    protected $_position ;

    public function __construct($db, $html = true)
    {
        $this->_profiler = $db->getProfiler();
        $this->_html = $html;
        $this->_position = 0;
        $this->_profiles = $this->_profiler->getQueryProfiles();
    }

    public function setOutputFormatToHtml($value)
    {
        $this->_html = !empty($value);
    }

    public function __toString()
    {
        $out = "";

        if ($this->_html) {
            foreach ($this->_profiles as $key => $query) {
                $out .= $this->_formatProfileAsHtml($key, $query);
            }
        } else {
            foreach ($this->_profiles as $key => $query) {
                $out .= $this->_formatProfileAsText($key, $query);
            }
        }

        return $out;
    }

    protected function _formatProfileAsHtml($key, $query)
    {
        $out = "&lt;pre&gt;&lt;code&gt;{$key}. " . wordwrap($query->getQuery(), 150) . "\n\n ({$query->getElapsedSecs()} s.) &lt;/code&gt; &lt;/pre&gt;";
        return $out;
    }

    protected function _formatProfileAsText($key, $query)
    {
        $out = "$key. {$query->getQuery()} ({$query->getElapsedSecs()} s.)\n\n";
        return $out;
    }

    public function rewind()
    {
        $this->_position = 0;
    }

    public function current()
    {
        if ($this->_html) {
            return $this->_formatProfileAsHtml($this->_position, $this->_profiles[$this->_position]);
        } else {
            return $this->_formatProfileAsText($this->_position, $this->_profiles[$this->_position]);
        }
    }

    public function key()
    {
        return $this->_position;
    }

    public function next()
    {
        ++$this->_position;
    }

    public function valid()
    {
        return isset($this->_profiles[$this->_position]);
    }
}
</pre>
<p>To make Zend Framework aware of the profiler action helper add the following lines of code to the bootstrap file:</p>
<pre name="code" class="php:nogutter">Zend_Controller_Action_HelperBroker::addHelper(
    new Company_Product_Helper_Profiler($config, $databaseConnection)
);</pre>
<p>When done the output of the profiler should look something like this:</p>
<p><a href="http://www.thedeveloperday.com/wp-content/uploads/2010/02/sql-profiler.png"><img src="http://www.thedeveloperday.com/wp-content/uploads/2010/02/sql-profiler.png" alt="" title="sql profiler" width="551" height="201" class="alignnone size-full wp-image-530" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/zend-framework-database-profiler-reporting/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Domain Model Logic Patterns</title>
		<link>http://www.thedeveloperday.com/domain-model-logic-patterns/</link>
		<comments>http://www.thedeveloperday.com/domain-model-logic-patterns/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 00:03:59 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[Domain Model]]></category>
		<category><![CDATA[Model]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[transaction-script]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=203</guid>
		<description><![CDATA[A great thing about patterns is that it provides a vocabulary. It allows developers to communicate efficiently. Complex ideas can be described at a high technical level without going into small details. Patterns are like butterflies and come in many colors, sizes and shapes and there&#8217;s.. lots of them. As butterflies patterns are grouped into families. One [...]]]></description>
			<content:encoded><![CDATA[<p>A great thing about <strong>patterns</strong> is that it provides a vocabulary. It allows developers to communicate efficiently. Complex ideas can be described at a high technical level without going into small details. Patterns are like butterflies and come in many colors, sizes and shapes and there&#8217;s.. lots of them. As butterflies patterns are grouped into families. One of such families is <strong>Domain Logic Patterns</strong> described in Martin Fowler&#8217;s book Patterns of Enterprise Application Architecture.</p>
<p>It&#8217;s one of the fundamental families because virtually every application written is described by any of the three patterns that belong to it. To say it simply there are three major ways how an application can be designed. What is more interesting that each of those patterns can be sorted by the amount of effort required to change the application depending on it&#8217;s complexity. Deciding which pattern to choose can be tricky because these patterns depend on various characteristics of the project being developed. The size, the complexity, the lifetime of a project and most importantly the skills of the developers.</p>
<h2>Transaction Script</h2>
<p><strong>Transaction script</strong> organizes business logic by routines where each routine handles a single request from the <strong>presentation layer</strong>. It is the most common way how software beginners write applications. Required steps to perform a task are identified and expressed using language semantics. Common routines can be broken into subroutines. Transaction Scripts can be organised as classes or as global functions. A single file can contain many Transaction Scripts at once. A lot of developers may think they are proficient OOP users while in reality they write data centric Transactions Scripts wrapping them into classes which could be just as easily replaced with simple procedures.</p>
<p>However Transaction scripts have benefits. It&#8217;s a simple <strong>procedural model</strong> so most developers can understand it, it works well with a simple data access layer using <strong>Row Data Gateway</strong> or <strong>Table Data Gateway</strong>.</p>
<p>An example transaction script may be booking a hotel room where a single procedure is responsible for checking the availability of the room, calculating the price and updating the database.</p>
<pre name="code" class="php:nogutter">
class Hotel
{
	public function __construct(Data_Access_Gateway $gateway)
	{
		$this->_gateway = $gateway;
	}  

	public function bookRoom($userId, $fromDate, $toDate)
	{
		$roomId = $this->_gateway->_getRoomIdBetweenDates($dateFrom, $dateTo);  

		if (!$roomId) {
			return false;
		}  

		$days = $this->_getAmountOfDays($fromDate, $toDate);  

		if ($days < = 7) {
			$price = $days * 100;
		} else {
			$price = $days * 80;
		}

		$data = array(
			'userId' => $userId,
			'roomId' => $roomId,
			'fromDate' => $fromDate,
			'toDate' => $toDate,
			'price' => $price,
		);  

		$bookingId = $this->_gateway->insert('bookings', $data);  

		return $bookingId;
	}
}
</pre>
<h2>Table Module</h2>
<p>A <strong>Table Module</strong> is many ways the middle man between a Transaction Script and a <strong>Domain Model</strong>. A Table Module tends to organize domain logic with one class per table in the database. While a Transaction Script will have one class Hotel to do reservations a Table Module may have more fine grained classes like Hotel, Booking, Room. Even though these classes may be singular they do not actually represent individual entities and manages whole collections of entities. For example a Booking class would be responsible for mosts actions performed on the bookings database table. Like a Transaction Script a Table Module is a very <strong>data centric</strong> model approach and usually has a strong connection with the <strong>data access layer</strong>.</p>
<p>Table Module has a few benefits over a Transaction Script. There&#8217;s less duplication, domain logic is more organized and structured around domain entities. It works well with simple data access layers. However, Table Module doesn&#8217;t give you full power of objects in organizing complex domain logic. It lacks instance to instance relationships, has weak support for <strong>polymorphism</strong>.</p>
<p>To show an example of Table Module let&#8217;s re-factor the Transaction Script:</p>
<pre name="code" class="php:nogutter">
class Hotel
{
	public function __construct(Data_Access_Gateway $gateway, Booking $booking)
	{
		$this->_gateway = $gateway;
		$this->_booking = $booking;
	}  

	public function bookRoom($userId, $fromDate, $toDate)
	{
		$roomId = $this->_booking->getRoomBetweenDates($fromDate, $toDate);

		if (!$roomId) {
			return false;
		}  

		$days = $this->_getAmountOfDays($fromDate, $toDate);  

		if ($days < = 7) {
			$price = $days * 100;
		} else {
			$price = $days * 80;
		}

		$bookingId = $this->_booking->addBooking($userId, $roomId, $fromDate, $toDate, $price);  

		return $bookingId;
	}
}

class Booking
{
	public function __construct(Data_Access_Gateway $gateway)
	{
		$this->_gateway = $gateway;
	}

	public function getRoomBetweenDates($dateFrom, $dateTo)
	{
		return $this->_gateway->getRoomBetweenDates($dateFrom, $dateTo);
	}

	public function addBooking($userId, $roomId, $fromDate, $toDate, $price)
	{
		$data = array(
			'userId' => $userId,
			'roomId' => $roomId,
			'fromDate' => $fromDate,
			'toDate' => $toDate,
			'price' => $price,
		);  

		$bookingId = $this->_gateway->insert('bookings', $data);  

		return $bookingId;
	}
}
</pre>
<h2>Domain Model</h2>
<p><strong>Domain Model</strong> organizes domain logic into well defined domain entities that contain both behavior and data. Usually each entity class represents a single entity in the <strong>data layer</strong>. Domain Model creates a hierarchy of inter connected objects that interact with each other by triggering behaviors on each other. Domain Model shines over Transaction Script and Table Module when it comes to handling <strong>domain complexity</strong>. It enables the full power of <strong>object oriented programming</strong> and all available design patterns. Even though Domain Model may sound like a silver bullet to all software development problems it is not. Learning to design applications using Domain Model requires a &#8220;paradigm shift&#8221; to start looking for entities and behaviors instead of looking for routines. The main downside of Domain Model is the way it works with relational databases. To compare I would like to quote Martin Fowler:</p>
<p>&#8220;<em>In many ways Domain Model treats the relational database like a crazy aunt who&#8217;s shut up in an attic and whom nobody wants to talk about.</em>&#8221;</p>
<p>Domain Model tries to be data layer agnostic. This is what <strong>object relational mappers</strong> also known as ORM&#8217;s as Hibernate try to solve by hiding the data access layer away.</p>
<p>To show an awkwardly simple example of Domain Model let&#8217;s re-factor the Table Module approach. To keep the example simple I&#8217;ll ignore the data access layer.</p>
<pre name="code" class="php:nogutter">
class Hotel
{
	protected $_hotelId;
	protected $_rooms;

	public function bookRoom(User $user, $fromDate, $toDate)
	{
		$room = $this->_getRoomBetweenDates($fromDate, $toDate);

		if (is_null($room)) {
			return false;
		}  

		$booking = $room->bookRoom(User $user, $fromDate, $toDate);

		return $booking;
	}
}

class Room
{
	protected $_roomId;
	protected $_bookings = array();

	public function bookRoom(User $user, $fromDate, $toDate)
	{
		$days = $this->_getAmountOfDays($fromDate, $toDate);

		if ($days < = 7) {
			$booking = new Booking($user, new ShortBookingStrategy($user, $days));
		} else {
			$booking = new Booking($user, new NormalBookingStrategy($user, $days));
		}

		return $booking;
	}
}

class NormalBookingPriceStrategy extends BookingPriceStrategy
{
	public function getPrice()
	{
		$price = $this->_days * 80;

		if ($this->_user->isLoyal()) {
			$price = $price / 2;
		}

		return $price;
	}
}

class ShortBookingPriceStrategy extends BookingPriceStrategy
{
	public function getPrice()
	{
		return $this->_days * 100;
	}
}
</pre>
<p>As you can see there is an instant explosion of classes and the data access layer is out of the picture. Responsibility to efficiently load and keep track of loaded entities is left to object mappers like Hibernate.</p>
<h2>The End</h2>
<p>Everyone of these domain model patterns have their benefits and downsides. It takes experience to be able to  decide which approach to take. For those who are new to <strong>Domain Model</strong> it is advised to have an experienced team member who is able to guide you through it. While <strong>Transaction Script</strong> or <strong>Table Module</strong> can seem like a good solution at some point it may not be as effective later on. It is important to recognize when a different domain model approach might work better. It&#8217;s been a long ride for me. Through the years I&#8217;ve learned a few things about designing software but I still don&#8217;t feel very comfortable writing about it. I would love to hear feedback from you how this article and these examples could be improved to enable better understanding between the different modeling approaches.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/domain-model-logic-patterns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating websites with Drupal cons and pros</title>
		<link>http://www.thedeveloperday.com/creating-websites-with-drupal-cons-and-pros/</link>
		<comments>http://www.thedeveloperday.com/creating-websites-with-drupal-cons-and-pros/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 22:15:36 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[modules]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=215</guid>
		<description><![CDATA[Recently I&#8217;ve set myself of a new journey since I&#8217;ve decided to help my friend&#8217;s business to  battle the crisis back home by creating them a new website. It&#8217;s a bit ironic but I didn&#8217;t know where to start, because at work I usually work with custom made websites which very rarely use a content management system. [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve set myself of a new journey since I&#8217;ve decided to help my friend&#8217;s business to  battle the crisis back home by creating them a new <a title="Kokybiški nestandartiniai baldai" href="http://www.kokybiski-baldai.lt">website</a>. It&#8217;s a bit ironic but I didn&#8217;t know where to start, because at work I usually work with custom made websites which very rarely use a content management system.</p>
<p>The content management system I&#8217;ve chosen to use is <a href="http://www.drupal.org">Drupal</a> &#8211; a widely adopted opensource content management system written in PHP. It has a vast community and enormous amounts of modules developed by other people. It took me about a week&#8217;s worth of evenings to get to know the system and launch the website. Here are the steps involved to create a Drupal website:</p>
<ul>
<li><strong>Install Drupal</strong>. The installation was really easy and simple. Put it on your webserver, access the website, follow an easy guide and you&#8217;re done.</li>
<li><strong>Configure Drupal</strong>. To a new user Drupal configuration may seem hectic or chaotic at first. It may take a while to get the hang of things. Figuring out how to change website information, setting up menus, changing themes, hiding things that you don&#8217;t want to display.</li>
<li><strong>Pick a theme</strong>. It&#8217;s generally better to pick an already made theme and modify it to fit your needs. Themes are designed to integrate with Drupal nicely. They will likely look the same on all popular browsers, will be HTML standard compliant, optimized for SEO and may even be optimized usability wise. I found it very easy to pick a theme using <a href="http://themegarden.org/">theme garden</a>.</li>
<li><strong>Install modules</strong>. Drupal is a modular content management system and comes with a few useful bundled modules it self. One of the strongest Drupal&#8217;s key points is that it has a vast community actively developing modules for it. If you ever need to do something on your website most likely there is a module to do it.</li>
</ul>
<h2>More about modules</h2>
<p>Drupal has many useful modules such as Blog, Comments, RSS, Forum, Search, Localization, Content categorization. But the true power lies in modules developed by the Drupal community. A few examples:</p>
<ul>
<li><a href="http://drupal.org/project/cck">CCK</a>. Content construction kit allows you to add custom fields to content nodes.</li>
<li><a href="http://drupal.org/project/views">Views</a>. One of the most essential modules for Drupal. Alows to change website&#8217;s representation in many ways.</li>
<li><a href="http://drupal.org/project/pathauto">Pathauto</a>. Allows to configure how website&#8217;s URL&#8217;s are constructed. A very powerful module for anyone interested in SEO.</li>
<li><a href="http://drupal.org/project/nodewords">Nodewords</a>. Allows to change meta tags. Very useful to provide custom meta descriptions for content pages. Descriptions are important for SEO.</li>
<li><a href="http://drupal.org/project/page_title">Page Title</a>. Another useful Drupal SEO module that allows to provide custom page titles.</li>
<li><a href="http://drupal.org/project/lightbox2">Lightbox2</a>. Very nice plugin to display images on the website. Also supports slideshow.</li>
<li><a href="http://drupal.org/project/wysiwyg">Wysiwyg</a>. Allows to replace a simple content text editor with a rich text editor of your choice.</li>
<li><a href="http://drupal.org/project/google_analytics">Google Analytics</a>. Adds google analytics tracking. Provides powerful per user configuration.</li>
<li><a href="http://drupal.org/project/node_gallery">Node Gallery</a>. A nice lightweight image gallery for Drupal. Still in alpha stages but very easy to use and provides lot&#8217;s of configuration. Integrates with Lightbox2.</li>
<li><a href="http://drupal.org/project/backup_migrate">Backup and Migrate</a>. Creates scheduled website backups in case there&#8217;s an emergency.</li>
<li>And many <a href="http://drupalmodules.com/top-rated">other modules</a>&#8230;</li>
</ul>
<h2>Pros and Cons of Drupal</h2>
<p>Drupal has many pros:</p>
<ul>
<li>Extremely easy to install on any webserver.</li>
<li>Has a vast community developing modules and providing technical help.</li>
<li>Has a huge amount of freely available themes to pick from.</li>
<li>Is very well adopted and maintained which means that bugs are fixed, security patches are released and new cutting edge features are always on the horizon.</li>
<li>Drupal is fast. Maybe it&#8217;s not the fastest content management system in the world but it certainly is fast. It&#8217;s very easy to set Drupal cache settings which give an immediate boost to the website.</li>
<li>It&#8217;s relatively easy to set up a website that is Search Engine Optimized aka SEO.</li>
</ul>
<p>Like everything in life Drupal has a few cons:</p>
<ul>
<li>For new users Drupal may be overwhelming somewhat chaotic and hectic. It&#8217;s still very easy to set up a theme and enter content. But you may have to scratch your head for a while how to add localization support to Drupal.</li>
<li>Drupal is quite old and even it&#8217;s actively developed lot&#8217;s of it is written in procedural PHP. Which isn&#8217;t necessarily a bad thing, but in some way means that it&#8217;s not a top cutting edge software modelling masterpiece.</li>
<li>Even though Drupal has a huge community which develops modules for it some of the modules don&#8217;t have very good documentation. More often than not these are the less used ones. It&#8217;s not Drupal&#8217;s fault but it&#8217;s still confusing and somewhat frustrating to try and figure out where and how you can configure some module you&#8217;ve just installed.</li>
</ul>
<p>All in all I&#8217;m happy with Drupal and I think it&#8217;s an amazing project and I&#8217;m giving my <strong>thanks </strong>to the Drupal community for all the greats things they are doing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/creating-websites-with-drupal-cons-and-pros/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

