<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">

  <channel>
    <title>Dave Marshall's Software Blog</title>
    <link href="http://davedevelopment.co.uk/"/>
    <atom:link href="http://davedevelopment.co.uk/rss.xml" rel="self" type="application/rss+xml" />
    <description>LAMP web application development, Software Engineering and
    other things</description>
    <language>en-gb</language>
    <pubDate>Thu, 09 May 2013 14:19:07 nil</pubDate>
    <lastBuildDate>Thu, 09 May 2013 14:19:07 nil</lastBuildDate>

    
    <item>
      <title>Silex Route Helpers for a Cleaner Architecture</title>
      <link>http://davedevelopment.co.uk/2012/11/27/silex-route-helpers-for-a-cleaner-architecture.html</link>
      <pubDate>Tue, 27 Nov 2012 10:00:00 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/11/27/silex-route-helpers-for-a-cleaner-architecture</guid>
      <description>&lt;p&gt;In a previous post, we discussed creating your &lt;a href=&quot;/2012/10/03/Silex-Controllers-As-Services.html&quot;&gt;Silex controllers as
Services&lt;/a&gt;, in which we created a
nice, clean, easily tested controller, with few dependencies and collaborators.
But I cheated a little, by returning a JSON response. Supposing we want to
render some HTML, do we want to inject the template engine in to the controller?
Should the controller be responsible for knowing how to render the template? I'm
not sure, but if I can have it not do it with minimal fuss, I think I'd rather
it not.  The full stack framework has the
&lt;a href=&quot;http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/view.html&quot;&gt;@Template&lt;/a&gt;
annotation, which allows developers to assign a template to a controller and
then simply return an array. If they can do it in the full stack framework, we
can do it in Silex.&lt;/p&gt;

&lt;div class=&quot;alert-message info&quot; markdown=&quot;1&quot;&gt;
This example is a little contrived, as the controller we end up with actually
does nothing, so much so, that I've not even printed the method here. A better
example would have the controller performing some sort of application specific
logic, such as emailing the author, or updating some statistics, or whatever
else you can think of. 
&lt;/div&gt;


&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;/&lt;em&gt;*
 * What we're aiming for
 &lt;/em&gt;/
$app-&gt;get(&quot;/posts/{post}&quot;, &quot;posts.controller:viewAction&quot;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-&amp;gt;convert(&quot;post&quot;, $app['findOr404Factory'](&quot;Demo\Entity\Post&quot;))
-&amp;gt;template(&quot;post/edit.html.twig&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;h2&gt;FindOr404Factory&lt;/h2&gt;

&lt;p&gt;This is really simple, if you're using doctrine, it simply creates closures for
us that attempt to find an instance of the class we provide with the Id of the
first argument, pretty much like the
&lt;a href=&quot;http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html&quot;&gt;@ParamConverter&lt;/a&gt; annotation,
without as much flexibility.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;$app['findOr404Factory'] = $app-&gt;protect(function($type, $message = null) use ($app) {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (null === $message) {
    $lastNamespace = strrpos($type, &quot;\\&quot;);

    if ($lastNamespace !== false) {
        $message = substr($type, strrpos($type, &quot;\\&quot;) + 1) . &quot; Not Found&quot;;
    } else {
        $message = &quot;$type Not Found&quot;;
    }
}

return function($id) use ($app, $type, $message) {

    $obj = $app['em']-&amp;gt;getRepository($type)-&amp;gt;find($id);

    if (null === $obj) {
        return $app-&amp;gt;abort(404, $message);
    }

    return $obj;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;h2&gt;Custom Route Class&lt;/h2&gt;

&lt;p&gt;In order to have our nice template helper, we need to tell Silex to use a custom
Route Class. This is pretty easy, but needs to be done before declaring any
routes.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;class CustomRoute extends Route
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public function template($path)
{
    $this-&amp;gt;setOption('_template', $path);
    return $this;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;/&lt;em&gt;* ... &lt;/em&gt;/&lt;/p&gt;

&lt;p&gt;$app['route_class'] = 'CustomRoute';&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;h2&gt;TemplateRenderingListener&lt;/h2&gt;

&lt;p&gt;Out of the box, Silex comes with a listener that will attempt to convert
anything you return from a controller (except for a &lt;code&gt;Response&lt;/code&gt; object) to a
string, and create a new Response with it. We need one of these, that will take
an array and render a template if the route has one.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;class TemplateRenderingListener implements EventSubscriberInterface
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected $app;

public function __construct(Application $app)
{
    $this-&amp;gt;app = $app;
}

public function onKernelView(GetResponseForControllerResultEvent $event)
{
    $response = $event-&amp;gt;getControllerResult();
    if (!is_array($response)) {
        return;
    }

    $request = $event-&amp;gt;getRequest();
    $routeName = $request-&amp;gt;attributes-&amp;gt;get('_route');
    if (!$route = $this-&amp;gt;app['routes']-&amp;gt;get($routeName)) {
        return;
    }

    if (!$template = $route-&amp;gt;getOption('_template')) {
        return;
    }

    $output = $this-&amp;gt;app['twig']-&amp;gt;render($template, $response);
    $event-&amp;gt;setResponse(new Response($output));
}

public static function getSubscribedEvents()
{
    return array(
        KernelEvents::VIEW =&amp;gt; array('onKernelView', -10),
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;/&lt;em&gt;* ... &lt;/em&gt;/&lt;/p&gt;

&lt;p&gt;$app['dispatcher']-&gt;addSubscriber(new TemplateRenderingListener($app));&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;Job's a good'un. The code can be seen together in &lt;a href=&quot;https://gist.github.com/4151421&quot;&gt;this
gist&lt;/a&gt;, I haven't got a full working example I
can publish at this time, but I can assure you it works! Hopefully you can see
from this post how flexible Silex is, but also how much of a great reference the
full stack framework is for whenever you want to do something new with your
Silex boilerplate.&lt;/p&gt;

&lt;p&gt;What we've ended up with is a &lt;code&gt;PostController::viewAction&lt;/code&gt; method that doesn't
care where the &lt;code&gt;Post&lt;/code&gt; comes from and doesn't care how it's presented. All it
care's about is the fact that the Post is being viewed, and what behaviour it
should apply to the application domain, based on that fact. This soon goes to
pot when you want to start redirecting to generated urls, persisting to the
database etc but hey, one step at a time. Even then, it wouldn't take much to add a
route helper that listens for a true boolean response and redirects to a given
url. Same goes for a helper that would automatically flush Doctrine's Unit Of
Work to the database, I'd be a little concious of doing that, but you
get the idea.&lt;/p&gt;

&lt;p&gt;One thing I would like to explore is applying security to the routes and their
parameters, much like you can with the
&lt;a href=&quot;http://jmsyst.com/bundles/JMSSecurityExtraBundle/master/annotations&quot;&gt;JMSSecurityExtraBundle&lt;/a&gt;,
but that's for another day. I think the convert methods are applied literally
last thing before executing the controller, so that might prove tricky.&lt;/p&gt;

&lt;p&gt;I also should write about why I use Silex instead of the full stack framework...&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Coding DCI in PHP</title>
      <link>http://davedevelopment.co.uk/2012/11/16/coding-dci-in-php.html</link>
      <pubDate>Fri, 16 Nov 2012 11:59:00 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/11/16/coding-dci-in-php</guid>
      <description>&lt;p&gt;I've been trying to further my knowledge a lot recently and it has taken me out
of my comfort zone quite often, but I think it's a great way to learn. One of
the things I came across a while back was &lt;a href=&quot;http://en.wikipedia.org/wiki/Data,_Context,_and_Interaction&quot;&gt;Data, Context and Interaction
(DCI)&lt;/a&gt;, but it
wasn't until I heard &lt;a href=&quot;https://twitter.com/saturnflyer&quot;&gt;Jim Gay&lt;/a&gt; talking about it
on the &lt;a href=&quot;http://devhell.info/&quot;&gt;/dev/hell&lt;/a&gt; podcast that I thought about taking a
closer look, particularly back in my comfort zone of the PHP ecosystem. Further
reading took me to &lt;a href=&quot;http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby&quot;&gt;The Right Way to Code DCI in
Ruby&lt;/a&gt;,
which I used to drive my PHP DCI experiment.&lt;/p&gt;

&lt;div class=&quot;well&quot; markdown=&quot;1&quot;&gt;
I wont go in to DCI theory too
much, but there are lot's of articles around the web, if you fancy some deeper
reading, Jim Gay has a book (currently beta) available at
[clean-ruby.com](http://clean-ruby.com). I've not read it yet, but people are
saying great things about it.
&lt;/div&gt;


&lt;h2&gt;User Stories&lt;/h2&gt;

&lt;p&gt;Taken straight from the aforementioned post, our story is &quot;As a user, I want to
add a book to my cart&quot;. We can write a feature for that:&lt;/p&gt;

&lt;p&gt;``` gherkin
Feature: User adds a book to their cart&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;In order to purchase a book
As a user
I need to be able to add the book to my cart

Scenario: User adds a book to their cart
    Given I am a logged in user
    And a book exists
    And I am looking at the book's page
    When I click the add book to cart button
    Then the book should be in my cart
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;h2&gt;The &quot;Roles&quot;&lt;/h2&gt;

&lt;p&gt;PHP is not Ruby. PHP is defintely not Ruby. We've not actually written any code
and we've hit our first sticking point. Ruby allows dynamic method injection
and PHP does not. As such, I'm going to wrap our data with a role and delegate
to it. This doesn't strictly adhere to the OOP utopia that DCI requires, but it
is in &quot;the spirit of DCI&quot; (see &lt;a href=&quot;http://mikepackdev.com/blog_posts/26-dci-role-injection-in-ruby&quot;&gt;comments in this
post&lt;/a&gt;). We
could come up with some magic solution, such as a trait that allows binding of
closures to the data object, but I'm quite happy with the cleanness of this
solution, without introducing a lot of userland magic.&lt;/p&gt;

&lt;p&gt;Specs first, I'm using my own toy framework for this, I haven't really had chance to
checkout &lt;a href=&quot;http://phpspec.org&quot;&gt;phpspec2&lt;/a&gt; and get fully up to speed on it.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;use BookShop\Entity\User;
use BookShop\Entity\Book;
use BookShop\Role\Customer;&lt;/p&gt;

&lt;p&gt;describe(&quot;BookShop\Role\Customer&quot;, function() {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;beforeEach(function() {
    $user = new User();
    $this-&amp;gt;customer = new Customer($user);
});

describe(&quot;#addToCart&quot;, function() {
    it(&quot;puts the book in the cart&quot;, function() {
        $book = new Book;
        $this-&amp;gt;customer-&amp;gt;addToCart($book);
        assertThat($this-&amp;gt;customer-&amp;gt;getCart()-&amp;gt;hasBook($book), true);
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;To hide away the actual delegation, I'm using a simple trait, you can see it in
the &lt;a href=&quot;https://github.com/davedevelopment/dci-example&quot;&gt;repo&lt;/a&gt;;&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;namespace BookShop\Role;&lt;/p&gt;

&lt;p&gt;use BookShop\Entity\Book;
use BookShop\Entity\User;
use BookShop\Util\Delegator;&lt;/p&gt;

&lt;p&gt;class Customer
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use Delegator;

public function __construct(User $user)
{
    $this-&amp;gt;delegateTo($user);
}

public function addToCart(Book $book)
{
    $this-&amp;gt;getCart()-&amp;gt;addBook($book);
}  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}
```&lt;/p&gt;

&lt;p&gt;Note: I've used a fairly loose interface here, I think ideally
the argument passed to the constructor would need to be something like a &lt;code&gt;CartOwner&lt;/code&gt;,
allowing other types of object (anything that has a getCart method) to become a &lt;code&gt;Customer&lt;/code&gt;.
Maybe we'll have &lt;code&gt;Visitor&lt;/code&gt; objects, for people who don't want to become a
registered user etc.&lt;/p&gt;

&lt;h2&gt;The &quot;Context&quot;&lt;/h2&gt;

&lt;p&gt;I hit another stumbling block here. Because we are wrapping our data with our
&lt;code&gt;Customer&lt;/code&gt; role, we create a hard dependency on that class, making it difficult
to mock. There are ways around this, I've seen some implemetations that pass the
Role in to the Context, but I think that definitely goes against the &quot;spirit of
DCI&quot;, another way would be to optionally inject a factory into the context,
specifically for testing, but seeing as we're dealing with a fairly simple
interaction, I'll just use concrete instances.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;use BookShop\Context\AddToCartContext;
use BookShop\Entity\User;
use BookShop\Entity\Book;&lt;/p&gt;

&lt;p&gt;describe(&quot;BookShop\Context\AddToCartContext&quot;, function() {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;beforeEach(function() {
    $this-&amp;gt;user = new User();
    $this-&amp;gt;book = new Book();
    $this-&amp;gt;context = new AddToCartContext($this-&amp;gt;user, $this-&amp;gt;book);
});

it(&quot;creates a customer&quot;, function() {
    assertThat($this-&amp;gt;context-&amp;gt;getCustomer(), anInstanceOf(&quot;BookShop\Role\Customer&quot;));
});

it(&quot;adds the book to the customers cart&quot;, function() {
    $this-&amp;gt;context-&amp;gt;execute();
    assertThat($this-&amp;gt;context-&amp;gt;getCustomer()-&amp;gt;getCart()-&amp;gt;contains($this-&amp;gt;book), true);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;Another slight deviation here, we can't have a class method and an instance method
called by the same name in PHP, so I just skipped the class method. Here's the
implementation:&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;namespace BookShop\Context;&lt;/p&gt;

&lt;p&gt;use BookShop\Entity\User;
use BookShop\Entity\Book;
use BookShop\Role\Customer;&lt;/p&gt;

&lt;p&gt;class AddToCartContext
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected $customer;
protected $book;

public function __construct(User $user, Book $book)
{
    $this-&amp;gt;customer = new Customer($user);
    $this-&amp;gt;book = $book;
}

public function execute()
{
    $this-&amp;gt;customer-&amp;gt;addToCart($this-&amp;gt;book);
}

public function getCustomer()
{
    return $this-&amp;gt;customer;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}
```&lt;/p&gt;

&lt;h2&gt;The &quot;Data&quot;&lt;/h2&gt;

&lt;p&gt;I won't go in to that here, but our data classes are just POPOs and I use
doctrine to persist them to the database. The relational side of things isn't
perfect (you can only have one copy of a book in your cart), but that's not the
focus of this. Admittedly, if I had a more robust data model (&lt;code&gt;User -&amp;gt; Cart -&amp;gt;
CartItem -&amp;gt; Book&lt;/code&gt;), to make doctrine
fit might mean the &lt;code&gt;Customer#addToCart&lt;/code&gt; method gets a little more complicated,
though maybe that would be extra justification for using DCI and putting that logic in a Role.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;namespace BookShop\Entity;&lt;/p&gt;

&lt;p&gt;class Book
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected $name;

/**
 * Getter/Setters etc
 */
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}
```&lt;/p&gt;

&lt;h2&gt;Fitting Into Silex&lt;/h2&gt;

&lt;p&gt;I'm a big fanboy of &lt;a href=&quot;http://silex.sensiolabs.org&quot;&gt;Silex&lt;/a&gt;, so here's how the context gets used in my controller:&lt;/p&gt;

&lt;p&gt;``` php&lt;/p&gt;

&lt;p&gt;$app-&gt;post(&quot;/cart&quot;, function(Book $book) use ($app) {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(new BookShop\Context\AddToCartContext($app-&amp;gt;user(), $book))-&amp;gt;execute();
$app['em']-&amp;gt;flush();
return $app-&amp;gt;redirect($app-&amp;gt;path(&quot;book_view&quot;, array(&quot;book&quot; =&amp;gt; $book-&amp;gt;getId())));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;})-&gt;convert(&quot;book&quot;, /&lt;em&gt; fetch book using id in request &lt;/em&gt;/);&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;We create the context and execute it and then flush changes to our datastore&lt;/p&gt;

&lt;h2&gt;Final Words&lt;/h2&gt;

&lt;p&gt;I quite enjoyed investigating DCI and in conclusion, despite PHP's
implementation shortcomings, I think pursuing the &quot;spirit of DCI&quot; in PHP is a
viable pursuit. It's quite possible that PHP's limitations in the architecture
side may prove beneficial, in that DCI may be communicated more as the paradigm,
separating the domain, the use cases and the roles, rather than just the code
injection.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Silex Controllers as Services</title>
      <link>http://davedevelopment.co.uk/2012/10/03/Silex-Controllers-As-Services.html</link>
      <pubDate>Wed, 03 Oct 2012 01:04:01 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/10/03/Silex-Controllers-As-Services</guid>
      <description>&lt;div class=&quot;alert-message &quot; markdown=&quot;1&quot;&gt;
    **UPDATE**: The functionality described below is now baked in to Silex,
    checkout the [ServiceControllerServiceProvider](http://silex.sensiolabs.org/doc/providers/service_controller.html).
&lt;/div&gt;




&lt;div class=&quot;alert-message info&quot; markdown=&quot;1&quot;&gt;
    **TL;DR** Use a custom controller resolver to load controllers
    from the service container - [code][code]
&lt;/div&gt;


&lt;p&gt;I'll start by saying this is rarely the right thing to do with &lt;a href=&quot;http://silex.sensiolabs.org&quot; title=&quot;Silex - The PHP micro-framework based on Symfony2 Components&quot;&gt;Silex&lt;/a&gt;. It's meant
to be a micro framework, so if you're going to be building something that
requires organising controllers in separate files or modules, maybe the full
stack &lt;a href=&quot;http://symfony.com&quot; title=&quot;High Performance PHP Framework for Web Development&quot;&gt;symfony framework&lt;/a&gt; would be a better choice. However, if you're like me and
have gradually evolved a legacy application to be a Silex application, you may
be in a situation where you want to try and keep things organised.&lt;/p&gt;

&lt;p&gt;There's currently a pull request in the queue for Silex that adds a cookbook
entry for [using controller classes][Cookbook], but I wanted to take it a step
further and have my controllers as services, much like &lt;a href=&quot;http://symfony.com/doc/current/cookbook/controller/service.html&quot;&gt;what's
possible&lt;/a&gt; with the full symfony framework (See &lt;a href=&quot;http://richardmiller.co.uk/2011/04/15/symfony2-controller-as-service/&quot;&gt;Richard
Miller's post&lt;/a&gt; for further reading).&lt;/p&gt;

&lt;p&gt;Things are best explained with an example, so let's start with this simple silex
app:&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;use Silex\Application;
use Demo\Repository\PostRepository;&lt;/p&gt;

&lt;p&gt;$app = new Application;&lt;/p&gt;

&lt;p&gt;$app['posts.repository'] = $app-&gt;share(function() {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;return new PostRepository;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;$app-&gt;get('/posts.json', function() use ($app) {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;return $app-&amp;gt;json($app['posts.repository']-&amp;gt;findAll());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;First we need to tell Silex how we're going to map routes to our controllers. We
do this by overriding the controller resolver with our own custom resolver. We
can take the existing controller resolver and override the &lt;code&gt;createController&lt;/code&gt;
method. If we encounter a single colon in the controller name, we look to see if the
string before the colon is a service, if it is, then we return a simple PHP
callback array.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;namespace Demo\Controller;&lt;/p&gt;

&lt;p&gt;use Silex\ControllerResolver as BaseControllerResolver;&lt;/p&gt;

&lt;p&gt;class ControllerResolver extends BaseControllerResolver
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected function createController($controller)
{
    if (false !== strpos($controller, '::')) {
        return parent::createController($controller);
    }

    if (false === strpos($controller, ':')) {
        throw new \LogicException(sprintf('Unable to parse the controller name &quot;%s&quot;.', $controller));
    }

    list($service, $method) = explode(':', $controller, 2);

    if (!isset($this-&amp;gt;app[$service])) {
        throw new \InvalidArgumentException(sprintf('Service &quot;%s&quot; does not exist.', $controller));
    }

    return array($this-&amp;gt;app[$service], $method);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;We simply then override Silex's default resolver.&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php
$app['resolver'] = $app-&gt;share(function () use ($app) {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;return new Demo\Controller\ControllerResolver($app, $app['logger']);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});
```&lt;/p&gt;

&lt;p&gt;We can now convert our controller to be a class, add it to Silex as a service
ready to be instantiated, complete with dependencies, when needed:&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;namespace Demo\Controller;&lt;/p&gt;

&lt;p&gt;use Demo\Repository\PostRepository;
use Symfony\Component\HttpFoundation\JsonResponse;&lt;/p&gt;

&lt;p&gt;class PostController
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected $repo;

public function __construct(PostRepository $repo)
{
    $this-&amp;gt;repo = $repo;
}

public function indexJson()
{
    return new JsonResponse($this-&amp;gt;repo-&amp;gt;findAll());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;``` php
&amp;lt;?php
$app['posts.controller'] = $app-&gt;share(function() use ($app) {&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;return new PostController($app['posts.repository']);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;$app-&gt;get('/posts.json', &quot;posts.controller:indexJson&quot;);&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;If I'm honest, the jury is still out on this technique for me. The benefits are
that my controller code is a little more organised and I can actually practice
spec level BDD with my controllers, rather than just functional tests, but
sometimes I really just feel like throwing a closure in rather than knocking up
a class. Maybe it might work for you, maybe not. Thanks for reading, &lt;a href=&quot;https://github.com/davedevelopment/silex-service-controllers&quot;&gt;full code example on github&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How I'm doing TDD with PHP</title>
      <link>http://davedevelopment.co.uk/2012/06/06/how-im-doing-tdd.html</link>
      <pubDate>Wed, 06 Jun 2012 09:12:12 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/06/06/how-im-doing-tdd</guid>
      <description>&lt;p&gt;I've been watching the &lt;a href=&quot;http://destroyallsoftware.com&quot;&gt;Destroy All Software&lt;/a&gt;
back catalog over the last couple of months and it's really inspired me to up my
&lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;TDD&lt;/a&gt; game. I'm still
fairly new to TDD, I've written tests for a long time, but never really let it
lead my development...&lt;/p&gt;

&lt;h3&gt;Outside-In or Middle-Out&lt;/h3&gt;

&lt;p&gt;I think I'm a middle-out kind of guy, I usually start with the business domain and try
and decide what my API needs to offer. This means writing unit tests for some
sort of Service class. From there, I'll branch out in to TDDing this service's
collaborators.&lt;/p&gt;

&lt;h3&gt;Unit Tests&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/img/phpunit.png&quot; alt=&quot;PHPUnit Logo&quot; style=&quot;float:right; margin:0px 0px 20px 20px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I use &lt;a href=&quot;http://phpunit.de&quot;&gt;PHPUnit&lt;/a&gt; for my unit test needs, I think it's pretty
much the defacto xUnit framework for PHP, I just did a quick search for
SimpleTest and it's still hosted in SVN on SourceForge, enough said!&lt;/p&gt;

&lt;h4&gt;Granular&lt;/h4&gt;

&lt;p&gt;I try and write unit tests that are unit tests, not integration or functional
tests. They take small (granular) pieces of code and test them.&lt;/p&gt;

&lt;h4&gt;Complete Isolation&lt;/h4&gt;

&lt;p&gt;I write my unit tests in almost complete isolation. It can get pretty messy,
particular if you have a lot of 'glue' like services, bending several
collaborators to their will. I make heavy use of dependency injection in the
design of the code, and use lots of mock objects to isolate the
&lt;a href=&quot;http://en.wikipedia.org/wiki/System_under_test&quot;&gt;SUT&lt;/a&gt;, then
verifying a mixture of both behaviour and state, depending on how complex the SUT or it's
collaborators are.&lt;/p&gt;

&lt;p&gt;I've recently been putting in a lot of effort to relax the expectation
constraints on the mock objects I use, so they're wired for expectations, but I
don't verify them. This means I can test the behaviour of a method in individual
tests if necessary, without having to repeat test code. I use
&lt;a href=&quot;http://github.com/padraic/mockery&quot;&gt;mockery&lt;/a&gt; for this especially with
it's &lt;code&gt;shouldIgnoreMissing&lt;/code&gt; method, which essentially gets the mock to act
like a &lt;a href=&quot;http://en.wikipedia.org/wiki/Null_Object_pattern&quot;&gt;Null Object&lt;/a&gt;. I'm
hoping this will have the effect of making my tests easier to understand, in
that you can see I'm only trying to verify the behaviour described by this test
, and also I'm hoping it will lead to my tests being slightly less tied to
the implementation.&lt;/p&gt;

&lt;h4&gt;Speed&lt;/h4&gt;

&lt;p&gt;Writing tests in isolation like this means my unit tests are fast. I don't hit
any external services, I don't load any fixtures. My current test suite runs in
less than 2 seconds.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/img/testtime.png&quot; alt=&quot;Fast tests&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;Easy access&lt;/h4&gt;

&lt;p&gt;Gary from destroyallsoftware.com knows his way around vim. I had a look through
his &lt;a href=&quot;https://github.com/garybernhardt/dotfiles/blob/master/.vimrc&quot;&gt;.vimrc&lt;/a&gt; and ended up copying loads of stuff from it. One of the most useful
things I found is a few functions that will try and work out the test file for
the current class you are editing and vice-versa. &lt;code&gt;&amp;lt;leader&amp;gt;.&lt;/code&gt; will now switch
between my production code and my unit tests. &lt;code&gt;&amp;lt;leader&amp;gt;t&lt;/code&gt; will write the current
file and run those tests
(and will always remember the last run file, incase you switch back to
production code or another file). The same mapping with uppercase T will run the
tests and show PHPUnit's ascii code coverage report. This makes running tests so
easy, there's no excuse not to. Checkout my
&lt;a href=&quot;https://github.com/davedevelopment/dotfiles/blob/master/.vimrc&quot;&gt;.vimrc&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Fail first&lt;/h4&gt;

&lt;p&gt;I've been a lazy unit tester in the past, and probably wouldn't have made the
effort to ensure a test can and will fail under the right circumstances,
particularly when retro-fitting tests. With the nice easy access, mutating a
test so that it will fail and
running can easily be accomplished with less than a dozen keystrokes.&lt;/p&gt;

&lt;h4&gt;Fake it 'til you make it&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/img/redgreenrefactor.png&quot; alt=&quot;Red -&amp;gt; Green -&amp;gt; Refactor&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Something else I've not done before, this involves writing a test, writing the
minimum amount of code to make that test pass. Write another test, write the
minimum amount of code to make both tests pass, and so on.&lt;/p&gt;

&lt;h4&gt;Craving RSpec's DSL&lt;/h4&gt;

&lt;p&gt;Watching those videos on destroyallsoftware.com makes me crave the nice DSL that
comes with &lt;a href=&quot;http://rspec.info/&quot;&gt;RSpec&lt;/a&gt;. Duck punching the &lt;code&gt;should&lt;/code&gt; and &lt;code&gt;should_not&lt;/code&gt; methods on to
everything makes the expectations look swell, same goes for the &lt;code&gt;stub&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;For example, here's the example spec file given on the rspec website for a
bowling game&lt;/p&gt;

&lt;p&gt;``` ruby&lt;/p&gt;

&lt;h1&gt;bowling_spec.rb&lt;/h1&gt;

&lt;p&gt;require 'bowling'&lt;/p&gt;

&lt;p&gt;describe Bowling, &quot;#score&quot; do
  it &quot;returns 0 for all gutter game&quot; do&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bowling = Bowling.new
20.times { bowling.hit(0) }
bowling.score.should eq(0)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;  end
end
```&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.phpspec.net/documentation/getting-started.html&quot;&gt;PHPSpec&lt;/a&gt; goes some
way to trying to match it, but doesn't do enough to make me want to switch from
phpunit. The same example from the PHPSpec website:&lt;/p&gt;

&lt;p&gt;``` php
class DescribeNewBowlingGame extends \PHPSpec\Context&lt;br/&gt;
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;private $_bowling = null;  

public function before()  
{  
    $this-&amp;gt;_bowling = $this-&amp;gt;spec(new Bowling);  
}  

public function itShouldScore0ForGutterGame()  
{  
    for ($i=1; $i&amp;lt;=20; $i++) {  
        // someone is really bad at bowling!  
        $this-&amp;gt;_bowling-&amp;gt;hit(0);  
    }  
    $this-&amp;gt;_bowling-&amp;gt;score-&amp;gt;should-&amp;gt;equal(0);  
}  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}
```&lt;/p&gt;

&lt;p&gt;That's before getting into stubs and mocks! There's not a real lot that PHPSpec
can do, Ruby's syntax and flexibility plays straight in to rspec's hands. I
don't actually like the idea of duck punching in production code, but it's use
in a testing tool like this leads to an enjoyable experience.&lt;/p&gt;

&lt;p&gt;I've also gone to great lengths over the last few years to make proper use of
Dependency Injection or Inversion of Control in my code to really enable
isolated unit testing, Ruby's ability to duck punch objects and in this case
the so called 'singleton' object, makes it look pointless.  Rubyists seem to
write class methods everywhere, probably because they're so easy to mock and
therefore easy to test as a collaborator, but also I think there's a lot to do
with the libraries they use, like ActiveRecord. I'm sure there are other
benefits of my approach (de-coupling is generally a good thing), but perhaps it
would be nice to apply it a litte less liberally.&lt;/p&gt;

&lt;h3&gt;Integration Tests&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/img/behat.png&quot; alt=&quot;Behat Logo&quot; style=&quot;float:right; margin: 0px 0px 20px 20px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Writing unit tests in the way I've mentioned above simply isn't enough for most
types of system. Heavy use of mock objects can easily hide cracks in the
itegration between different systems, these need testing. For these purposes, I
use &lt;a href=&quot;http://behat.org&quot;&gt;Behat&lt;/a&gt;. These tests tend to test most of the stack, with
only a few external services, such as mail or third party APIs that are stubbed
out somehow. As such, these tests are fairly slow, taking over a minute to run.
At some point I intend to make a push and start testing some the of the UI
interaction, which will require a javascript enabled browser for these tests,
which will slow them down even further, despite recent breakthroughs with things
like &lt;a href=&quot;http://zombie.labnotes.org/&quot;&gt;Zombie.js&lt;/a&gt; and
&lt;a href=&quot;http://zombie.labnotes.org/&quot;&gt;PhantomJS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/img/behattime.png&quot; alt=&quot;Not quite as fast tests&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;Breaking the cucumber rules&lt;/h4&gt;

&lt;p&gt;I usually &lt;a href=&quot;http://elabs.se/blog/15-you-re-cuking-it-wrong&quot;&gt;cuke it wrong&lt;/a&gt; and I
don't write my features in the proper 'story BDD' style. My features aren't
really acceptance tests, they have fairly declaritive setups and steps, and
quite often involve mutliple actors, interacting as they would as part of a
workflow. I make full use of the standard
&lt;a href=&quot;http://mink.behat.org&quot;&gt;Mink&lt;/a&gt; DSL in order to rapidly develop features, rather
than grafting my own DSL on top to create nicer looking feature files and a
layer of abstraction that I probably wont use.&lt;/p&gt;

&lt;h3&gt;Continuous Integration&lt;/h3&gt;

&lt;p&gt;I'm a lone gunman in my current position, so continuous integration is
downplayed a little, but I have &lt;a href=&quot;http://sismo.sensiolabs.org&quot;&gt;Sismo&lt;/a&gt; configured
to run composer, phpunit and then behat after each commit. It plays sounds on
success/failure and does me for now. I did have Jenkins setup and pimped out to
the max via &lt;a href=&quot;http://jenkins-php.org/&quot;&gt;Jenkins-PHP&lt;/a&gt;, but I found I wasn't getting
much out of it.&lt;/p&gt;

&lt;p&gt;That's all for now, will maybe follow up in a couple more months with more about
my progress. I've recently picked up
&lt;a href=&quot;http://www.amazon.com/gp/product/0321503627/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=davedvd-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0321503627&quot;&gt;GOOS&lt;/a&gt;,
I'm sure I'll learn how I'm doing it wrong when I get through that.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why aren't you contributing to Open Source?</title>
      <link>http://davedevelopment.co.uk/2012/03/08/putting-code-out-there.html</link>
      <pubDate>Thu, 08 Mar 2012 12:38:18 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/03/08/putting-code-out-there</guid>
      <description>&lt;p&gt;I've been publishing a bit of code recently and I'm loving it! My current
job allows me to pick and choose the libraries and tools I use, and as such I've
been spending plenty of time analysing them, making good use of them and where
github's involved, giving back where I could. In the past I've submitted a
couple of patches through bug trackers, but in the last couple of months, I've
sent half a dozen, albeit minor pull requests to projects I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gocardless/gocardless-php/pull/4&quot;&gt;gocardless/gocardless-php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/composer/composer/pull/376&quot;&gt;composer/composer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fabpot/Sismo/pull/54&quot;&gt;fabpot/Sismo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Behat/Behat/pull/86&quot;&gt;Behat/Behat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Behat/Behat/pull/81&quot;&gt;Behat/Behat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Behat/Behat-docs/pull/29&quot;&gt;Behat/Behat-docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I've also started publishing more of my own work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/davedevelopment/housey&quot;&gt;davedevelopment/housey&lt;/a&gt; - Early
stages of a &lt;a href=&quot;http://www.bingocardcreator.com/abingo&quot;&gt;A/Bingo&lt;/a&gt; port to PHP&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/davedevelopment/stiphle&quot;&gt;davedevelopment/stiphle&lt;/a&gt; - A
simple PHP library for throttling things&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/davedevelopment/sismo-geckoboard-notifier&quot;&gt;davedevelopment/sismo-geckoboard-notifier&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;a href=&quot;https://github.com/fabpot/Sismo&quot;&gt;Sismo&lt;/a&gt; notifier for
&lt;a href=&quot;http://geckoboard.com&quot;&gt;Geckoboard&lt;/a&gt;, written to (possibly) submit to
&lt;a href=&quot;http://ibuildings.com/challenge&quot;&gt;Ibuilding's latest challenge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/1949917&quot;&gt;Audio notifier for Sismo (gist)&lt;/a&gt; - A really
simple notifier that I use, along with Super Mario sounds effects :)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I think I've got past the point of caring too much about what other people might
think about my work and standards like
&lt;a href=&quot;https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md&quot;&gt;PSR0&lt;/a&gt;
and tools like &lt;a href=&quot;http://getcomposer.org&quot;&gt;composer&lt;/a&gt; have made it easier for me to
create re-usable components that people may actually use. The
&lt;a href=&quot;https://github.com/davedevelopment/housey&quot;&gt;two&lt;/a&gt;
&lt;a href=&quot;https://github.com/davedevelopment/stiphle&quot;&gt;libraries&lt;/a&gt; I mentioned above
published aren't watched and haven't been forked yet, but someone may find them
useful one day! One of my other projects
&lt;a href=&quot;http://github.com/davedevelopment/phpmig&quot;&gt;phpmig&lt;/a&gt; has seen some use and has had
contributions from others.&lt;/p&gt;

&lt;p&gt;The next step is to get my teeth in to something a bit more involved, I've got
my eye on a particular issue in &lt;a href=&quot;http://github.com/composer/composer&quot;&gt;composer&lt;/a&gt;,
but I'm need to speak to the core devs to get some guidelines on how to proceed,
i.e. how much refactoring I can do without compromising the 1.0.0 release.&lt;/p&gt;

&lt;p&gt;In conclusion, &lt;a href=&quot;http://github.com&quot;&gt;Github&lt;/a&gt; makes it so easy, why aren't you contributing?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How I'm designing a RESTful(ish) web service</title>
      <link>http://davedevelopment.co.uk/2012/02/16/how-im-doing-rest.html</link>
      <pubDate>Thu, 16 Feb 2012 21:13:22 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/02/16/how-im-doing-rest</guid>
      <description>&lt;h3&gt;Introduction and Disclaimer&lt;/h3&gt;

&lt;p&gt;This post is going to describe how I've ending up designing, what I consider
to be a fairly &lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_state_transfer#RESTful_web_services&quot;&gt;RESTful web API&lt;/a&gt;. I'm far from being an expert, and this is definitely
the closest thing to a RESTful API that I've ever created, so I'm not even
experienced with REST APIs. So if I were you, I wouldn't take anything here as
REST gospel. If you've got some criticisms, let me know, I'm all about the
learning. There's also so much more to a RESTful architecture than what I
describe in this blog post, this is simply what it took for me to find my way on
to the path.&lt;/p&gt;

&lt;p&gt;Until about 6 months ago, I'd always been sceptical of creating RESTful APIs,
but I think I've had a few pennies drop since then that have made me
fairly confident that I grasp the basics pretty well.&lt;/p&gt;

&lt;p&gt;One of the biggest problems I've had was finding really good concreate examples,
but recently the &lt;a href=&quot;http://code.google.com/p/huddle-apis/wiki/BasicConcepts&quot;&gt;huddle-apis
documentation&lt;/a&gt; popped
up on my twitter timeline (via &lt;a href=&quot;http://twitter.com/bwaine&quot;&gt;@bwaine&lt;/a&gt;,
&lt;a href=&quot;http://twitter.com/dzuelke&quot;&gt;@dzuelke&lt;/a&gt; and
&lt;a href=&quot;http://twitter.com//darrel_miller&quot;&gt;@darrel_miller&lt;/a&gt;,) and I found it really useful.&lt;/p&gt;

&lt;h3&gt;Authentication&lt;/h3&gt;

&lt;p&gt;Something I wanted to clear up straight away was authentication. One of my
biggests misconceptions about REST was the 'Stateless' constraint. I took that
way too literally (or maybe I didn't and I now I'm just ignoring it).  I'm now
of the opinion that a session cookie is a valid way to authenticate a consumer
for a REST API. That said, I wanted to go better than that, so I went and
implemented &lt;a href=&quot;http://www.xml.com/pub/a/2003/12/17/dive.html&quot;&gt;WSSE authentication&lt;/a&gt; as described by the &lt;a href=&quot;http://www.xml.com/pub/a/2003/10/15/dive.html&quot;&gt;ATOM API&lt;/a&gt;. Now my application
supports both, so the API can be consumed via XHR from the websites pages, and
also by the more 'stateless' WSSE authenitcation headers. I've actually
implemented this using Symfony's security component, which could be an entire
blog post unto itself. In retrospect, I think I probably should have considered
&lt;a href=&quot;http://en.wikipedia.org/wiki/OAuth&quot;&gt;OAuth&lt;/a&gt;, but I always thought that was more
about authorisation than authentication.&lt;/p&gt;

&lt;h3&gt;Richardson Maturity Model&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/richardson.png&quot; alt=&quot;Richardson Maturity Model&quot;/&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://martinfowler.com/articles/richardsonMaturityModel.html&quot;&gt;Richardson Maturity
model&lt;/a&gt; is
where I started with regards to setting goals for designing the actual web service. My basic
knowledge of REST web services would have me meeting level 2 fairly easily, so I
needed to brush up on the two things that would take me fully to level 3.&lt;/p&gt;

&lt;h3&gt;HTTP Verbs - PUT vs POST&lt;/h3&gt;

&lt;p&gt;Admittedly I had a rough idea of correct use of the HTTP verbs, but the penny didn't
fully drop on the &lt;a href=&quot;http://benramsey.com/blog/2009/11/post-vs-put/&quot;&gt;POST vs.
PUT&lt;/a&gt; until I really started
digging in to articles. My take on it is now, if you're use &lt;code&gt;PUT&lt;/code&gt;, you'll always
be sending a full representation of the resource you expect to find at the URI
for that resource.  A &lt;code&gt;POST&lt;/code&gt; would generally be to create something where you
wouldn't necessarily know the URI of the newly created resource or where you
aren't sending  a full representation of the resource.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /messages&lt;/code&gt; - Add this message resource to the /messages collection (create)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT /messages&lt;/code&gt; - Store this collection of messages at /messages&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT  /messages/123&lt;/code&gt; - Store this message resource at /messages/123 (create or update)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /messages/123&lt;/code&gt; - Store these attributes in the message resource at /messages/123&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I don't think my interpretation would ring completely true with the purists, but it makes sense
in my mind and it gave me the chance to move on to more important things...&lt;/p&gt;

&lt;h3&gt;HATEOAS and Defining Media Types&lt;/h3&gt;

&lt;p&gt;I'm aiming to hit level 3 of the model, which means conforming with the &lt;a href=&quot;http://en.wikipedia.org/wiki/HATEOAS&quot;&gt;Hypermedia as the engine of application state
(HATEOAS)&lt;/a&gt; guiding principle. I'm not overly convinced by the whole principle within
the context of my requirements, but I thought I'd give it a shot.&lt;/p&gt;

&lt;p&gt;The first step for is to document the media types we're going to accept
and serve through the API.&lt;/p&gt;

&lt;p&gt;I decided to solely support JSON as the data format
I'll be providing to consumers. Every time I provide or consume XML, I hope it will
be the last, so I won't be bothering with that. I've no real interest in HTML
either, although it is nice to be able to browse APIs in a browser. With that in
mind, I did a bit of reading about &lt;a href=&quot;http://blog.stateless.co/post/13296666138/json-linking-with-hal&quot;&gt;HAL in
JSON&lt;/a&gt;, and liked most of what I
found, so decided to take a similar approach.&lt;/p&gt;

&lt;p&gt;I attended the &lt;a href=&quot;http://conference.phpnw.org.uk&quot;&gt;PHPNW conference&lt;/a&gt; last year, and picked up some good points about
media types from &lt;a href=&quot;http://www.twitter.com/blongden&quot;&gt;Ben Longden&lt;/a&gt;'s
&lt;a href=&quot;http://www.slideshare.net/blongden/rest-andthehypermediaconstraint&quot;&gt;talk&lt;/a&gt;, mainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't version the API, version the media types&lt;/li&gt;
&lt;li&gt;Leave room for expansion and you might not have to version the media types&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;You see a lot of APIs with URIs like /1/messages, where 1 would be the API
version. This goes against the REST grain, affectively describing a messages
resource in version 1 of the API, whereby /2/messages would actually be the same
resource, but in version 2 of the API. I'm hoping to never have to take that route, if my API changes that
drastically, I'll introduce a new version of the media types that are affected.
Thereby I'll be able to serve either the version 1 &lt;em&gt;representation&lt;/em&gt; of the
/messages resource, or the version 2 representation.&lt;/p&gt;

&lt;p&gt;Leaving room for expansion is an easy one. Rather than:&lt;/p&gt;

&lt;p&gt;``` javascript&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
    &quot;to&quot;: [&quot;dave@atstsolutions.co.uk&quot;]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;We'd do:&lt;/p&gt;

&lt;p&gt;``` javascript&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
    &quot;to&quot;: [{&quot;address&quot;: &quot;dave@atstsolutions.co.uk&quot;}]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;If we wanted to add more information to each recipient at some point, we could do so
without affecting existing consumers of the API.&lt;/p&gt;

&lt;h4&gt;Example - API Resource (our API's entry point)&lt;/h4&gt;

&lt;p&gt;Now, one of the HATEOAS principles is that the consumer should be able to
navigate to the resource they require from an original endpoint. I'm not really
too sure how narrow or wide that can be, but for argument's sake, I'm going to
have an API resource at the root URI of my API, with a media type of
&lt;code&gt;application/vnd.acme.api+json&lt;/code&gt;. This way consumers should be able to hit the root
uri to start with and navigate to the resource they need. Personally, I find it
very hard to imagine myself doing it, I'd be looking up the resource uri once
and then hard-coding it, but maybe that's just me.&lt;/p&gt;

&lt;p&gt;I'm currently documenting the media types on a single in my technical
documentation, so as an example, the API resource would look something like
this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;application/vnd.acme.api+json&lt;/code&gt; media type:&lt;/p&gt;

&lt;p&gt;``` javascript&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
    &quot;_links&quot;: {
        &quot;self&quot;: {&quot;href&quot;: &quot;/&quot;, &quot;type&quot;: &quot;application/vnd.acme.api+json&quot;},
        &quot;messages&quot;: {&quot;href&quot;: &quot;/&quot;, &quot;type&quot;: &quot;application/vnd.acme.messages+json&quot;}
    },
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;author&quot;: &quot;Dave Marshall&quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;I got introduced to &lt;a href=&quot;http://behat.org&quot;&gt;Behat&lt;/a&gt; when I worked at Sky Betting and Gaming, and it's been
an invaluable tool for me in the new job, particularly as it's enabled me to
quickly create automated tests for rickety old legacy php scripts, where unit
testing is out of the question. It's further worked out as a nice tool to both test and,
coupled with the media types documentation, document the API's usage as well as behaviour.&lt;/p&gt;

&lt;div class=&quot;well&quot; markdown=&quot;1&quot;&gt;
__[Cuking it Wrong](http://elabs.se/blog/15-you-re-cuking-it-wrong)__: 
I've been using behat to write *integration tests* for my API, rather
than *acceptance tests*. They're written by a developer, for developers and speak
REST over HTTP rather than the language of the domain. They're also fairly declaritive, I
find it easier to write specific tests and cover edge cases. I think it goes
against the grain of most people doing BDD with cucumber/behat, but it works for me.
&lt;/div&gt;


&lt;p&gt;Given our new endpoint, I can write a couple of simple scenarios covering the
end point and authentication:&lt;/p&gt;

&lt;p&gt;``` gherkin
Feature: Acme example API&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;In order to make things happen
As an API consumer
I need to make API calls

Scenario: Authentic consumer checks API details
    Given the following API users exist:
        | Username    | Password    |
        | username123 | password123 |
    And I am API user &quot;username123&quot; with password &quot;password123&quot;
    And I send &quot;wsse&quot; authentication
    And I accept &quot;application/vnd.acme.api+json&quot;
    When I send a GET request to &quot;/&quot;
    Then the api response status code should be &quot;200&quot;

Scenario: Authentic consumer checks API details with incorrect password
    Given the following API users exist:
        | Username    | Password    |
        | username123 | password    |
    And I am API user &quot;username123&quot; with password &quot;incorrectpassword&quot;
    And I send &quot;wsse&quot; authentication
    And I accept &quot;application/vnd.acme.api+json&quot;
    When I send a GET request to &quot;/&quot;
    Then the api response status code should be &quot;401&quot;

Scenario: Non-Authentic consumer checks API details
    Given the following API users exist:
        | Username    | Password    |
        | username123 | password    |
    And I am API user &quot;incorrectusername&quot; with password &quot;incorrectpassword&quot;
    And I send &quot;wsse&quot; authentication
    And I accept &quot;application/vnd.acme.api+json&quot;
    When I send a GET request to &quot;/&quot;
    Then the api response status code should be &quot;401&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;h4&gt;Example - Messages Resource&lt;/h4&gt;

&lt;p&gt;As I'm sure you noticed, the API resource representation example above includes
a link to a messages resource. Given that link, we can right some gherkin to
test the messages resource API.&lt;/p&gt;

&lt;p&gt;``` gherkin
Feature: Messages Resource API&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;In order to manage messages
As an API consumer 
I need to make create, read, update and delete messages resources

Background:
    Given the following API users exist:
        | Username    | Password    |
        | username123 | password123 |
        | username456 | password456 |
    And I am API user &quot;username123&quot; with password &quot;password123&quot;
    And I send &quot;wsse&quot; authentication
    And I accept &quot;application/vnd.acme.api+json&quot;
    When I send a GET request to &quot;/&quot;
    Then the api response status code should be &quot;200&quot;
    And I remember the JSON response value at &quot;_links/messages/href&quot; as &quot;messages_uri&quot;

Scenario: Authentic user retrieves a collection of messages
    Given the following messages exist:
        | From        | To          | Subject        | Body           |
        | username456 | username123 | Test Message 1 | Blah Blah Blah |
        | username456 | username123 | Test Message 2 | Blah Blah Blah |
    And I accept &quot;application/vnd.messages.api+json&quot;
    When I send a GET request to &quot;&amp;lt;messages_uri&amp;gt;&quot;
    Then the api response status code should be &quot;200&quot;
    And the JSON response should have 2 &quot;messages&quot;
    And the JSON response value at &quot;messages/1/_embedded/message/subject&quot; should be &quot;Test Message 2&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;This scenario above uses a background to 'navigate' to the messages resource uri
via the API resource described earlier, and then tests the messages resource
API. Let's take a look at the &lt;code&gt;application/vnd.acme.messages+json&lt;/code&gt; media type documentation.&lt;/p&gt;

&lt;p&gt;``` javascript
{&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&quot;_links&quot;: {
    &quot;self&quot;: { 
        &quot;href&quot;: &quot;/messages&quot;, 
        &quot;type&quot;: &quot;application/vnd.acme.messages+json&quot;
    },
    &quot;send-message&quot;: { 
        &quot;href&quot;: &quot;/messages/outbox&quot;, 
        &quot;type&quot;: &quot;application/vnd.acme.message+json&quot;,
        &quot;method&quot;: &quot;POST&quot;
    }
},
&quot;messages&quot;: [
    {
        &quot;_embedded&quot;: {
            &quot;_links&quot;: {
                &quot;self&quot;: {
                    &quot;href&quot;: &quot;/messages/1&quot;,
                    &quot;type&quot;: &quot;application/vnd.acme.message+json&quot;
                }
            },
            &quot;from&quot;: {
                &quot;name&quot;: &quot;username456&quot;
            },
            &quot;to&quot;: {
                &quot;name&quot;: &quot;username123&quot;
            },
            &quot;subject&quot;: &quot;Test Message 1&quot;,
            &quot;body&quot;: &quot;Blah Blah Blah&quot;
        }
    },
    {
        &quot;_embedded&quot;: {
            &quot;_links&quot;: {
                &quot;self&quot;: {
                    &quot;href&quot;: &quot;/messages/2&quot;,
                    &quot;type&quot;: &quot;application/vnd.acme.message+json&quot;
                }
            },
            &quot;from&quot;: {
                &quot;name&quot;: &quot;username456&quot;
            },
            &quot;to&quot;: {
                &quot;name&quot;: &quot;username123&quot;
            },
            &quot;subject&quot;: &quot;Test Message 2&quot;,
            &quot;body&quot;: &quot;Blah Blah Blah&quot;
        }
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;Whoa, a little verbose! This is definitely the downside to trying to stick with
the HATEOAS principles, but you kind of get used to it. A few things to note in
the example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Links - we've got a &lt;code&gt;send-message&lt;/code&gt; link, pretty self explanatory. I've added
the type and the method as attributes, as it's one thing I actually found to
be missing in HAL+JSON. Most of the time the HTTP method to use can be
assumed, but everything else is so explicit I thought why not. I'd do the same
in a HTML form, so why not in my JSON representation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Embedded Message - Rather than just a list of URIs to the individual messages, I've
embedded some of the message contents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;to&lt;/code&gt; attributes of the messages are both JSON objects. Right now they only
have a name attribute, but somewhere down the line we might introduce a &lt;code&gt;user&lt;/code&gt;
resource, at which point we could add links at the very least, if not embedded
information such as full name and other attributes a user may have.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Now we know where to find the hyperlink to send a message, we can write an
integration test that will discover the URI and create a message&lt;/p&gt;

&lt;p&gt;``` gherkin&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Authentic user sends a message 
    Given the following messages exist:
        | From        | To          | Subject        | Body           |
        | username456 | username123 | Test Message 1 | Blah Blah Blah |
        | username456 | username123 | Test Message 2 | Blah Blah Blah |
    When I send a GET request to &quot;&amp;lt;messages_uri&amp;gt;&quot;
    Then the api response status code should be &quot;200&quot;
    And I remember the JSON response value at &quot;_links/send-message/href&quot; as &quot;send-message-uri&quot;
    Given I accept &quot;application/vnd.message.api+json&quot;
    And I send &quot;application/vnd.message.api+json&quot;
    When I send a POST request to &quot;&amp;lt;send-message-uri&amp;gt;&quot; with the following:
        &quot;&quot;&quot;
        {
            &quot;from&quot;: {
                &quot;name&quot;: &quot;username123&quot;
            },
            &quot;to&quot;: {
                &quot;name&quot;: &quot;username456&quot;
            },
            &quot;subject&quot;: &quot;Hello&quot;,
            &quot;body&quot;: &quot;Blah Blah Blah&quot;
        }
        &quot;&quot;&quot;
    Then the api response status code should be &quot;201&quot;
    # and check the response attributes etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;And that's about it. I'm really happy with the progress I've made, but please
feel free to tear in to my practices in the comments below. I'll be back with
some more REST related posts, probably on my implementation with Silex and
probably some more details on the custom Behat contexts I'm using.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Defending against Cache Stampedes</title>
      <link>http://davedevelopment.co.uk/2012/01/13/defending-against-cache-stampedes.html</link>
      <pubDate>Fri, 13 Jan 2012 00:59:12 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2012/01/13/defending-against-cache-stampedes</guid>
      <description>&lt;blockquote&gt;
    &lt;p&gt;Bonnie, there's a stampede... in your tent!&lt;/p&gt;
    &lt;small&gt;Mitch Robbins - City Slickers(1991)&lt;/small&gt;
&lt;/blockquote&gt;


&lt;p&gt;I've recently had a problem with a rather large operation (that could probably
be optimised considerably, but nevermind), where by if the cached result of the
operation expired, several web server threads would attempt the operation,
causing some major headaches for our database and web servers. This is something
I've come across before, and is commonly(?) known as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Cache_stampede&quot;&gt;Cache
Stampede&lt;/a&gt;. This is bad, this post
describes the basics of what I've done to deal with it.&lt;/p&gt;

&lt;h3&gt;Basic Caching&lt;/h3&gt;

&lt;p&gt;Given a Big Fecking Operation, we wrap some simple code around it using a
Zend_Cache instance to cache the result for an hour - ignore the use of globals
and lack of otherwise good coding practices&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

function bfo9000() {
    sleep(5);
    return time();
}

function bfo9000_cached() {
    global $cache;
    $key = 'bfo9000_cache';
    $res = $cache-&amp;gt;load($key);
    if (false === $res) {
        $res = bfo9000();
        $cache-&amp;gt;save($res, $key, array(), 3600);
    }

    return $res;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Semaphores&lt;/h3&gt;

&lt;p&gt;Once we start to get stampedes, the first thing we want to do is try and limit
the amount of threads/processes that are going to try and regenerate the result
and store it in the cache again. We can do this using a &lt;a href=&quot;http://en.wikipedia.org/wiki/Semaphore_%28programming%29&quot;&gt;Binary
Semaphore&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Zend cache isn't exactly ideal for this, as the combination of
&lt;code&gt;test&lt;/code&gt; and &lt;code&gt;save&lt;/code&gt; are not atomic, using something like
&lt;a href=&quot;http://www.php.net/manual/en/memcached.add.php&quot;&gt;Memcached::add&lt;/a&gt; would be better
if you really want to avoid two processes generating the cached result.&lt;/p&gt;

&lt;p&gt;Our function will now be programmed, when getting a cache miss, to check to
see if the semaphore exists, if so, will sleep for a little while before
checking again. If it doesn't exists, it will create the semaphore itself,
before populating the cache and releasing the semaphore.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

function bfo9000_cached() {
    global $cache;
    $key = 'bfo9000_cache';
    $lockKey = 'bfo9000_cache_lock';
    $res = $cache-&amp;gt;load($key);
    if (false === $res) {

        while (false === $res &amp;amp;&amp;amp; $cache-&amp;gt;test($lockKey)) {
            sleep(1);
            $res = $cache-&amp;gt;load($key);
        }

        if (false === $res) {
            $cache-&amp;gt;save(true, $lockKey, array(), 10);
            $res = bfo9000();
            $cache-&amp;gt;save($res, $key, array(), 3600);
            $cache-&amp;gt;remove($cacheKey);
        }
    }

    return $res;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All being well, we should have prevented the stampede, as several of the threads
that require the result of the operation will wait while one (or maybe a few) do
the actual ground work.&lt;/p&gt;

&lt;h3&gt;Shortening the window&lt;/h3&gt;

&lt;p&gt;We've now prevented the stampede from bringing the servers to their knees, but
we're not necessarily providing the best experience for those consumers that
simply wait while the other threads do their stuff. To improve this,
we can manage the expiry of the cache ourselves and attempt to prime the cache before it fully expires. I'm not sure if there's a name for this technique, but it's mentioned on the
&lt;a href=&quot;http://code.google.com/p/memcached/wiki/FAQ#How_to_prevent_clobbering_updates,_stampeding_requests&quot;&gt;Memcached
FAQ&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Adam's pointed out that &lt;a href=&quot;https://www.varnish-cache.org/&quot;&gt;Varnish&lt;/a&gt;
would call this a
&lt;a href=&quot;https://www.varnish-cache.org/trac/wiki/VCLExampleGrace&quot;&gt;Grace&lt;/a&gt; Period&lt;/p&gt;

&lt;p&gt;We need to store the actual expiry with the data in the cache, rather than
relying on the cache software's expiry, luckily for my example,
&lt;a href=&quot;http://framework.zend.com/manual/en/zend.cache.html&quot;&gt;Zend_Cache&lt;/a&gt; does that for
us. When we get a cache hit, we check to see if the cached result is due to
expire &lt;strong&gt;soon&lt;/strong&gt;. If it is, we immediately update the cached result with an expiry date much
further in the future, and then set about updating the cache. This way, other
processes will see the cached result as valid while our process updates the
cache.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

function bfo9000_cached() {
    global $cache;
    $key = 'bfo9000_cache';
    $lockKey = 'bfo9000_cache_lock';
    $res = $cache-&amp;gt;load($key);
    if (false === $res) {

        while (false === $res &amp;amp;&amp;amp; $cache-&amp;gt;test($lockKey)) {
            sleep(1);
            $res = $cache-&amp;gt;load($key);
        }

        if (false === $res) {
            $cache-&amp;gt;save(true, $lockKey, array(), 30);
            $res = bfo9000();
            $cache-&amp;gt;save($res, $key, array(), 3600);
            $cache-&amp;gt;remove($cacheKey);
        }
    } else {
        $meta = $cache-&amp;gt;getMetaDatas($key);
        if ($meta['expire'] &amp;gt; time() + 300 &amp;amp;&amp;amp; !$cache-&amp;gt;test($lockKey)) {
            $cache-&amp;gt;touch($key, 3600);
            $cache-&amp;gt;save(true, $lockKey, array(), 30);
            $res = bfo9000();
            $cache-&amp;gt;save($res, $key, array(), 3600);
            $cache-&amp;gt;remove($lockKey);
        }
    }

    return $res;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; in the main else block, if the semaphore already exists, we leave
generating a new cached result to the process that's doing so and simply return
the result we already have.&lt;/p&gt;

&lt;h3&gt;Disclaimer&lt;/h3&gt;

&lt;p&gt;I wrote all of the code above right here in the post, please don't copy and paste it in
to your projects and complain to me if it doesn't work :) I think I've got it
just about right and it seems to work for me, let me know nicely of all the mistakes
I've made in the comments below.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Handling Symfony2 Events Asynchronously</title>
      <link>http://davedevelopment.co.uk/2011/11/02/handling-symfony-events-asynchronously.html</link>
      <pubDate>Wed, 02 Nov 2011 22:15:46 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/11/02/handling-symfony-events-asynchronously</guid>
      <description>&lt;div class=&quot;well&quot;&gt;

&lt;h4&gt;UPDATE 23/01/2012&lt;/h4&gt;
As &lt;a href=&quot;https://twitter.com/#!/khepin&quot;&gt;Sebastien&lt;/a&gt; pointed out in the
comments, Symfony 2.1's emails are sent after the page via a &lt;code&gt;kernel.terminate&lt;/code&gt;
event, which is cool! I don't know if there's any specific configuration
required, but &lt;a href=&quot;https://twitter.com/#!/fabpot&quot;&gt;Fabien&lt;/a&gt; &lt;a
href=&quot;https://twitter.com/#!/fabpot/status/147620340711964672&quot;&gt;tweeted about
it&lt;/a&gt;. Rather than going forward with what I propose in this blog post, you
could use the &lt;code&gt;kernel.terminate&lt;/code&gt; event, to improve perceived performance for your
users. Things would take place in process still, so taking up web server
resources, but it's a good first step.
&lt;/div&gt;


&lt;p&gt;I love Symfony2's &lt;a href=&quot;https://github.com/symfony/EventDispatcher&quot;&gt;Event Dispatcher&lt;/a&gt;
and find it's a really nice way of decoupling code, though admittedly it can
decouple things a little too much. One thing I constantly find, is that the
listeners I bind to events tend to be for sending notifications or other sorts
of logging, which in an ideal world, would be handled asynchronously. That is, why should
this user wait for their page response, just so your system can email the 10
people who want to know about what they did? Most people taking the leap to move
these functions offline would create message queues for each of those individual
listeners, or setup a new separate service bus, but I've had a look at
attaching a message queue to the existing symfony architecture, by creating a simple decorator for the event
dispatcher.&lt;/p&gt;

&lt;h2&gt;Example&lt;/h2&gt;

&lt;p&gt;You can get the &lt;a href=&quot;https://github.com/davedevelopment/symfony-firehose-example&quot;&gt;full example on
github&lt;/a&gt;, I'll just show snippets here as a
walkthrough. I'm using Silex for the example, but the same principles apply to a
full blown symfony application, or any app that's using the Event Dispatcher.&lt;/p&gt;

&lt;p&gt;Here some code for a simple JSON API to add a comment to a blog post. Notice
that the email is sent inline:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/**
 * Add a comment
 */
$app-&amp;gt;post('/blog/{post}/comments', function(Application $app, array $post) {

    $id = !empty($post['comments']) ? max(array_keys($post['comments'])) + 1 : 1;
    $comment = json_decode($app['request']-&amp;gt;getContent(), true);
    $comment['id'] = $id;
    $post['comments'][$id] = $comment;

    /**
     * Send an email to the author
     */
    mail($app['author'], 'New comment on ' . $post['title'], $comment['comment']);

    return new Response(
        json_encode($comment),
        201,
        array(
            'Content-type' =&amp;gt; 'application/json',
            'Location' =&amp;gt; &quot;/blog/{$post['id']}/comment/{$id}&quot;,
        )
    );
})-&amp;gt;convert('post', $postLookup);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Using Events&lt;/h2&gt;

&lt;p&gt;Our first improvement is to send that email via an event listener. First we add
a listener:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$app['dispatcher']-&amp;gt;addListener('blog.comments.new', function(Event $event) use ($app) {
    mail($app['author'], 'New comment on ' . $event-&amp;gt;post['title'], $event-&amp;gt;comment['comment']);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we alter the controller to fire an event rather than firing an email&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/**
 * Fire and event rather than sending an email
 */
$event = new Event;
$event-&amp;gt;post = $post;
$event-&amp;gt;comment = $comment;
$app['dispatcher']-&amp;gt;dispatch('blog.comments.new', $event);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a nice little improvement, we've decoupled sending the email from
the main purpose of the endpoint which is adding the comment. The problem is,
the sending of the email, which can be slow, still happens in the same
synchronous process, which we'll hope to overcome in the next few steps.&lt;/p&gt;

&lt;h2&gt;Firehose Event Dispatcher&lt;/h2&gt;

&lt;div class=&quot;well&quot;&gt;&lt;a href=&quot;http://twitter.com/glenathan&quot;&gt;@glenathan&lt;/a&gt; pointed
out that storing and switching on the async prefix wasn't necessary, so that's
been removed, see the &lt;a
href=&quot;https://github.com/davedevelopment/symfony-firehose-example/commit/0d0f5c6ae8a1d39ba23255f39f7d2c65868d3aa7&quot;&gt;full
changeset&lt;/a&gt; for details.&lt;/div&gt;


&lt;p&gt;I implemented this as a decorator (I think, I'm rubbish with patterns), and it
basically allows you to register listeners that will receive all events
dispatched through a given event dispatcher. Checkout the &lt;a href=&quot;https://github.com/davedevelopment/atst/blob/master/src/Atst/Symfony/Component/EventDispatcher/Decorator/FireHose.php&quot;&gt;source on
github&lt;/a&gt;.
In this example, we're going to use
the firehose to refire the event with a different event name:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$app['base_dispatcher'] = $app['dispatcher'];
$app['dispatcher'] = $app-&amp;gt;share(function($c) {
    $firehose = new FireHose($c['base_dispatcher']);
    return $firehose;
});

$app['dispatcher']-&amp;gt;addFireHoseListener(function($eventName, Event $event) use ($app) {
    /**
     * Disable the firehose, then fire the event again but with the async
     * prefix
     */
    $app['dispatcher']-&amp;gt;oneTimeDisableFireHose();
    $app['dispatcher']-&amp;gt;dispatch('async.' .  $eventName, $event);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we change the name of the event for our email sending listener&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$app['dispatcher']-&amp;gt;addListener('async.blog.comments.new', function(Event $event) use ($app)
    mail($app['author'], 'New comment on ' . $event-&amp;gt;post['title'], $event-&amp;gt;comment['comment']);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point, we're not doing anything asynchronously, but we've given our app
the ability to make a choice. Listeners can choose to listen on the regular
event name, or choose the asynchronous event name, by which they should expect
to be notified asynchronously.&lt;/p&gt;

&lt;h2&gt;Fire hosing on to a message queue&lt;/h2&gt;

&lt;p&gt;The next step is to change the firehose listener to one that will push the event
on to a message/job queue or service bus of some description. In this example,
I've used &lt;a href=&quot;http://www.zeromq.org/&quot;&gt;0MQ&lt;/a&gt; in a pub/sub type setup, but you can
insert anything you like in here. If you're interested in 0MQ, checkout &lt;a href=&quot;http://www.slideshare.net/IanBarber/zeromq-is-the-answer-php-tek-11-version&quot;&gt;Ian
Barber's Slides&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$app['dispatcher']-&amp;gt;addFireHoseListener(function($eventName, Event $event) use ($app) {
    /**
     * Dont bother with the silex or kernel events, in real life you'd probably 
     * want to switch this on class type of the event
     */ 
    if (0 !== strpos($eventName, 'kernel.') &amp;amp;&amp;amp; 0 !== strpos($eventName, 'silex.')) { 

        $eventName = 'async.' . $eventName;

        if ($app['dispatcher.async']) {
            $app['dispatcher.queue.pub']-&amp;gt;send(serialize(array($eventName, $event)));
        } else {
            // might be useful to have in process for dev
            $app['dispatcher']-&amp;gt;oneTimeDisableFireHose();
            $app['dispatcher']-&amp;gt;dispatch($eventName, $event);
        }
    }
});

$app['dispatcher.queue.pub.dsn'] = 'tcp://localhost:5567';
$app['dispatcher.queue.sub.dsn'] = 'tcp://localhost:5566';
$app['dispatcher.queue.pub'] = $app-&amp;gt;share(function($c) {
    $ctx = new ZMQContext();
    $send = $ctx-&amp;gt;getSocket(ZMQ::SOCKET_PUSH);
    $send-&amp;gt;connect($c['dispatcher.queue.pub.dsn']);
    return $send;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/davedevelopment/symfony-firehose-example/blob/master/refire.php&quot;&gt;source on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's an important point here, note the exclusion of the kernel and silex
events, these events dont serialize. If you want to pop your Events on a queue
and have them handled elsewhere, they need to be in a portable format. Events
that implement the &lt;a href=&quot;http://uk.php.net/Serializable&quot;&gt;serializable interface&lt;/a&gt;
would be a good start, but you might want to consider what other systems may
want to get to the data and use a format like JSON.&lt;/p&gt;

&lt;p&gt;Now to create a little daemon to pull things off the queue and refire the event
like we did before:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$app = include __DIR__.'/app.php';
$ctx = new ZMQContext();
$sub = $ctx-&amp;gt;getSocket(ZMQ::SOCKET_SUB);
$sub-&amp;gt;setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, '');
$sub-&amp;gt;connect($app['dispatcher.queue.sub.dsn']);
$poll = new ZMQPoll();
$poll-&amp;gt;add($sub, ZMQ::POLL_IN);
$read = $wri = array();
while(true) {
    $ev = $poll-&amp;gt;poll($read, $wri, 5000000);
    if ($ev &amp;gt; 0) {
        list($eventName, $event) = unserialize($sub-&amp;gt;recv());
        echo &quot;Refiring $eventName\n&quot;;
        $app['dispatcher']-&amp;gt;oneTimeDisableFireHose();
        $app['dispatcher']-&amp;gt;dispatch($eventName, $event);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/davedevelopment/symfony-firehose-example/blob/master/refire.php&quot;&gt;source on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last but not least, we need a 0MQ server to sit in the middle:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ctx = new ZMQContext();
$pub = $ctx-&amp;gt;getSocket(ZMQ::SOCKET_PUB);
$pub-&amp;gt;bind('tcp://*:5566');
$pull = $ctx-&amp;gt;getSocket(ZMQ::SOCKET_PULL);
$pull-&amp;gt;bind('tcp://*:5567');

while(true) {
    $message = $pull-&amp;gt;recv();
    $pub-&amp;gt;send($message);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/davedevelopment/symfony-firehose-example/blob/master/server.php&quot;&gt;source on github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Putting it all together&lt;/h2&gt;

&lt;p&gt;I know it's a rather crude example, but what you end up with is a pretty simple
way of turning synchronous events into asynchronous ones.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/async.png&quot; alt=&quot;Example Output&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It would be nice to hear other people's thoughts on this, hit me up with some
comments. I know it seems a bit messy, but I'm betting there's quite a few
symfony sites wired up with events that could benefit from having a few taken
offline?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Phpmig - Simple migrations for php</title>
      <link>http://davedevelopment.co.uk/2011/11/01/phpmig-simple-migrations-for-php.html</link>
      <pubDate>Tue, 01 Nov 2011 00:15:46 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/11/01/phpmig-simple-migrations-for-php</guid>
      <description>&lt;p&gt;I've got a serious &lt;a href=&quot;http://en.wikipedia.org/wiki/Not_Invented_Here&quot;&gt;Not Invented Here&lt;/a&gt; syndrome problem when it comes to (database) migrations.&lt;/p&gt;

&lt;p&gt;I've previously blogged about &lt;a href=&quot;/how-to-simple-database-migrations-with-phing-and-dbdeploy.html&quot;&gt;migrations with phing and dbdeploy&lt;/a&gt; and also &lt;a href=&quot;/notes-from-porting-ruby-to-php.html&quot;&gt;porting ActiveRecord::Migrations to PHP&lt;/a&gt;, now here I am again blogging about yet another way of doing migrations in PHP projects. Only maybe this time it's different, maybe this time I've found a way I'm happy with...?&lt;/p&gt;

&lt;p&gt;My requirements were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ability to run 'interleaved' migrations&lt;/li&gt;
&lt;li&gt;Migrate/rollback&lt;/li&gt;
&lt;li&gt;Not tied to any framework/library or particular way of configuring your app&lt;/li&gt;
&lt;li&gt;Migrations must be able to execute code, plain SQL isn't enough - think data
manipulation, or migrating XML files etc&lt;/li&gt;
&lt;li&gt;Pretty console colours&lt;/li&gt;
&lt;li&gt;Easy install&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;a href=&quot;http://github.com/davedevelopment/phpmig&quot;&gt;Phpmig&lt;/a&gt; is a simple migrations system that was written to be easily adopted regardless of the framework or libraries you are using. It requires a little bit of setting up, but if you know you should be using migrations, you're probably more than capable.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/phpmig.png&quot; alt=&quot;Phpmig status command&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;It's really simple&lt;/h2&gt;

&lt;p&gt;On it's own, it doesn't really do a lot. It runs migrations.&lt;/p&gt;

&lt;p&gt;You have to tell it where your migrations are. You have to tell it where to record which migrations have been run. You do this by passing it something that implements the &lt;a href=&quot;http://php.net/manual/en/class.arrayaccess.php&quot;&gt;ArrayAccess&lt;/a&gt; interface, with at least two keys, phpmig.adapter and phpmig.migrations. The former needs to be an instance of &lt;a href=&quot;https://github.com/davedevelopment/phpmig/blob/master/src/Phpmig/Adapter/AdapterInterface.php&quot;&gt;Phpmig\Adapter\AdapterInterface&lt;/a&gt;, and allows phpmig to record and decide which migrations have been run. The latter is an array of migration files.&lt;/p&gt;

&lt;p&gt;For this, I recommend using &lt;a href=&quot;http://pimple.sensiolabs.org/&quot;&gt;Pimple&lt;/a&gt;, a small service/dependency injection container, there's a version bundled under the Phpmig namespace, &lt;a href=&quot;https://github.com/davedevelopment/phpmig/blob/master/src/Phpmig/Pimple/Pimple.php&quot;&gt;Phpmig\Pimple\Pimple&lt;/a&gt;. The nice thing is, the very same ArrayAccess object is accesible from your migration files. Phpmig doesn't provide you with a way of accessing your database, seeing as that's probably quite specific to your project, depending on the module you're working on, or the environment you're working on, you'll have to take care of it yourself.&lt;/p&gt;

&lt;h2&gt;Example Applicaiton&lt;/h2&gt;

&lt;p&gt;If you want to get stuck in straight away, checkout the &lt;a href=&quot;https://github.com/davedevelopment/phpmig/blob/master/README.md&quot;&gt;README&lt;/a&gt;, otherwise read on for a simple usage example.&lt;/p&gt;

&lt;p&gt;I'm going to use &lt;a href=&quot;http://silex.sensiolabs.org/&quot;&gt;Silex&lt;/a&gt; as the base for my example app, for two reasons. Firstly it's really nice, second because it uses an instance of Pimple as a service container.&lt;/p&gt;

&lt;p&gt;A little setup first:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd ~/src
$ mkdir phpmig-example-app
$ cd phpmig-example-app
$ wget http://silex.sensiolabs.org/get/silex.phar
$ mkdir vendor
$ git submodule add https://github.com/doctrine/dbal vendor/doctrine-dbal
$ git submodule add https://github.com/doctrine/common vendor/doctrine-common
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can move on to writing our app. Rather than having what's essentially the bootstrap in the index file, I put everything in a file called app.php&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

// app.php

require_once __DIR__.'/silex.phar';

$app = new Silex\Application();

$app-&amp;gt;get('/hello/{name}', function($name) use($app) {
    return 'Hello '.$app-&amp;gt;escape($name);
});

$app-&amp;gt;register(new Silex\Provider\DoctrineServiceProvider(), array(
    'db.options'            =&amp;gt; array(
        'driver'    =&amp;gt; 'pdo_sqlite',
        'path'      =&amp;gt; __DIR__.'/app.db',
    ),
    'db.dbal.class_path'    =&amp;gt; __DIR__.'/vendor/doctrine-dbal/lib',
    'db.common.class_path'  =&amp;gt; __DIR__.'/vendor/doctrine-common/lib',
));

return $app;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The index file simply includes the app.php file and runs the app.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php 

// index.php

$app = include __DIR__.'/app.php';

$app-&amp;gt;run();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's our app built, so now we can phpmig it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo pear channel-discover pear.atstsolutions.co.uk
$ sudo pear install atst/phpmig-alpha
$ cd ~/src/phpmig-example-app
$ phpmig init
+d ./migrations Place your migration files in here
+f ./phpmig.php Create services in here
$
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Phpmig has created a phpmig bootstrap file for us, but it's very basic:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

use \Phpmig\Adapter,
    \Phpmig\Pimple\Pimple;

$container = new Pimple();

$container['phpmig.adapter'] = $container-&amp;gt;share(function() {
    // replace this with a better Phpmig\Adapter\AdapterInterface 
    return new Adapter\File\Flat(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/.migrations.log');
});

$container['phpmig.migrations'] = function() {
    return glob(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/*.php');
};

return $container;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We don't need to use phpmig's bundled version of pimple, and we've got ourselves a nice doctrine connection setup in our app, so we may as well use that to record the running of our migrations, rather than a flat file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

use \Phpmig\Adapter;

$container = include __DIR__.'/app.php';

$container['phpmig.adapter'] = $container-&amp;gt;share(function($c) {
    return new Adapter\Doctrine\DBAL($c['db'], 'migrations');
});

$container['phpmig.migrations'] = function() {
    return glob(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/*.php');
};

return $container;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see if things are working by running phpmig's status command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ phpmig status

 Status   Migration ID    Migration Name 
-----------------------------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now create our first migration. Phpmig will create a skeleton for us, but we have to give it a name and a place to put it&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ phpmig generate CreateFirstTable ./migrations
+f ./migrations/20111101000144_CreateFirstTable.php
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The file it generates contains two empty methods, up and down.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

use Phpmig\Migration\Migration;

class CreateFirstTable extends Migration
{
    /**
     * Do the migration
     */
    public function up()
    {

    }

    /**
     * Undo the migration
     */
    public function down()
    {

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As our service container has a db connection for us to use, we can use that to
create (or drop) our table.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

use Phpmig\Migration\Migration;

class CreateFirstTable extends Migration
{
    /**
     * Do the migration
     */
    public function up()
    {
        $c = $this-&amp;gt;getContainer();
        $c['db']-&amp;gt;query(&quot;
            CREATE TABLE `user` (
                `id` INTEGER,
                `name` TEXT,
                PRIMARY KEY (`id`)
            );
        &quot;);
    }

    /**
     * Undo the migration
     */
    public function down()
    {
        $c = $this-&amp;gt;getContainer();
        $c['db']-&amp;gt;query(&quot;DROP TABLE IF EXISTS `user`;&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All that's left now is to run the migration we've just created&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ phpmig status

 Status   Migration ID    Migration Name 
-----------------------------------------
   down  20111101000144  CreateFirstTable

$ phpmig migrate
 == 20111101000144 CreateFirstTable migrating
 == 20111101000144 CreateFirstTable migrated 0.0037s
$ phpmig status

 Status   Migration ID    Migration Name 
-----------------------------------------
     up  20111101000144  CreateFirstTable

$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Comments, Feedback and Patches&lt;/h2&gt;

&lt;p&gt;All are welcome, it's still in it's infancy, but I'm using it on a couple of
projects already and I'm fairly happy with it. I've not created pear
packages (or indeed run a pear server) before, so go easy on me if I've screwed
anything on that side of things.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rambling On</title>
      <link>http://davedevelopment.co.uk/2011/10/25/rambling-on.html</link>
      <pubDate>Tue, 25 Oct 2011 00:11:12 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/10/25/rambling-on</guid>
      <description>&lt;p&gt;2010 and 2011 have been very big years for me. Towards the backend of 2010, my
beautiful daughter was born and my then girlfriend and I got engaged. Since
then, I landed a great new job at &lt;a href=&quot;http://www.skybet.com&quot;&gt;Sky Betting and Gaming&lt;/a&gt;
 as a Senior Software Engineer, and now I've moved on again to
work for a small startup in the form of &lt;a href=&quot;http://www.childcare.co.uk&quot;&gt;Childcare.co.uk&lt;/a&gt;. And now I've updated my
blog!&lt;/p&gt;

&lt;h2&gt;Sky Betting and Gaming&lt;/h2&gt;

&lt;p&gt;I took the decision in May to move on from
&lt;a href=&quot;http://www.cspencerltd.co.uk&quot;&gt;Spencer's&lt;/a&gt;, I still enjoyed the job but felt
that having been there for 7 years, across 5 (or maybe even 6) positions, I'd
finally become pretty limited in terms of capacity for growth, so when I got the opportunity to go to
&lt;a href=&quot;http://skybet.com&quot;&gt;SkyBet&lt;/a&gt;, I took it. It did mean a one hour commute each way
but I was going to be working with a high quality team on a big site
and with plenty of scope for improvement and progression.&lt;/p&gt;

&lt;p&gt;Things went really well there and I really enjoyed it. It was nice to leave the
management responsibilities behind at Spencers and go to Sky and just get stuck
in to the code, and at first I found the code base quite overwhelming, but I picked
things up and spent most of my time working on a JSON-RPC web service for
placing bets.&lt;/p&gt;

&lt;p&gt;It also gave me my first chance to be fully immersed in agile methods, mainly
following &lt;a href=&quot;http://scrumalliance.org&quot;&gt;Scrum&lt;/a&gt;, but there was a definite hint of
&lt;a href=&quot;http://leansoftwareengineering.com/ksse/scrum-ban/&quot;&gt;Scrum-ban&lt;/a&gt; creeping into
the life cycle, particularly when we had a fixed deadline invoked by the
management team.&lt;/p&gt;

&lt;p&gt;Sky seem to take good care of their staff, the working environment, nature of the
work and the benefits package where all on the money, it was just unfortunate
for me that another opportunity arose so quickly. I think Sky are hiring at the
minute, so it's worth checking their &lt;a href=&quot;http://www.workforsky.com/work_for_sky/search_and_apply_bus_areas.htm&quot;&gt;job
listings&lt;/a&gt;
if you're on the lookout for new opportunities.&lt;/p&gt;

&lt;p&gt;Before my last week they were good enough to let me join the team in going to
&lt;a href=&quot;http://phpnw.org&quot;&gt;PHPNW&lt;/a&gt;, I think there were about 10 of the technology team in
attendance, all funded by the company, so they've got that part right as well.
As always I enjoyed the conference, some talks more than others, but I mainly
enjoy the social side of things anyway.&lt;/p&gt;

&lt;h2&gt;Childcare.co.uk&lt;/h2&gt;

&lt;p&gt;I've worked on &lt;a href=&quot;http://childcare.co.uk&quot;&gt;Childcare.co.uk&lt;/a&gt; as a freelancer in the
past, and as the site has seen excellent growth in the two and a half years it's
been running, I was approached by the owner about joining them full-time. I've
been in the job a week now and I'm really enjoying it, working for a much
smaller company means I can rapidly make decisions and move towards being truly
agile (I pushed 3 releases today!). It also allows me to engage in more
architectural type decisions when the opportunity arises, decisions that I
didn't really have the capacity to make as a freelancer when I've worked with
them in the past and the kind of decisions that were made by more senior staff
at Sky. I also get to work from home full-time!&lt;/p&gt;

&lt;p&gt;In terms of what I'll be doing, I've got a good mix of general site
enhancements, new features and a whole new sister project. The company is on the
verge of launching mobile apps as well, and while it's hardly a specialty of
mine, I wouldn't mind having a look around at some of that stuff.&lt;/p&gt;

&lt;p&gt;I'm definitely going to miss the team atmosphere they have at Sky, I seemed to
get along well enough with everyone there, and working at home on my own will be
a stark contrast. To counter that a little, I'm going to make more effort with
the networking events that are not too far away from me, starting with &lt;a href=&quot;http://leedsphp.org/&quot;&gt;PHP
Leeds&lt;/a&gt; and maybe even &lt;a href=&quot;http://hulldigital.co.uk&quot;&gt;Hull
Digital&lt;/a&gt;. It'd be really cool to get to one of the
&lt;a href=&quot;http://www.meetup.com/HNLondon/&quot;&gt;HNLondon&lt;/a&gt; meetups, but that's a bit of a trek
for me.&lt;/p&gt;

&lt;h2&gt;Blog&lt;/h2&gt;

&lt;p&gt;Apologies to anyone who subscribes to the feed and got a barrage of crappy old
posts, I'm not entirely sure what I goosed up there, but I saw the damage it did
to my Google Reader experience.&lt;/p&gt;

&lt;p&gt;The blog's now running on
&lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt;, a static site generator
that powers github pages. It's really cool and means I can hack together blog
posts in markdown, push them to a repo and have them deployed automatically. It
took a bit of getting set up and I've lost all the comments from the old
wordpress blog, but I couldn't be bother to try and import them into
&lt;a href=&quot;http://disqus.com&quot;&gt;Disqus&lt;/a&gt;. The design was really nice and easy thanks to
&lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter Bootstrap&lt;/a&gt;, much better than my
previous 'programmer design' work you've seen up here.&lt;/p&gt;

&lt;p&gt;I don't think the comments are working at the minute, probably because
&lt;a href=&quot;http://disqus.com&quot;&gt;Disqus&lt;/a&gt; haven't got the DNS change through yet, but if they
are and you fancy leaving me some feedback, it's always appreciated.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Traits in PHP 5.4 - HelloWorld with Logging Trait</title>
      <link>http://davedevelopment.co.uk/2011/08/05/traits-in-php-5-4-helloworld-with-logging-trait.html</link>
      <pubDate>Fri, 05 Aug 2011 23:08:45 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/08/05/traits-in-php-5-4-helloworld-with-logging-trait</guid>
      <description>&lt;p&gt;I'm looking forward to having traits in PHP 5.4 :)&lt;/p&gt;

&lt;p&gt;One of the 'traits' I find myself constantly adding to library files is optional logging of it's behaviour. The library class has it's own log method, that checks to see if the instance has had a logger injected and if so, logs the message. I see this as a perfect candidate for becoming a reusable trait, as I tend to have the same code copy/pasted throughout my library classes.&lt;/p&gt;

&lt;p&gt;The problem is, according to the &lt;a href=&quot;https://wiki.php.net/rfc/traits&quot;&gt;rfc&lt;/a&gt;, traits aren't supposed to have state/properties, which makes it difficult to have a DI setter method in a trait. I guess it provides further protection against clashes, but you could always make the property name very unique, though I suppose that not a particularly good practice. However, setting properties in the traits seems to work just fine, so here's a quick demo of adding logging capabilities to a class via traits in PHP 5.4. Needless to say, because this may be undesired behaviour and it's only an alpha release, I'm not banking on this working in the future.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

/**
 * Logging trait
 */
trait Logging
{
    /**
     * @var Zend_Log
     */
    protected $_logger = null;

    /**
     * Set logger
     *
     * @param Zend_Log $logger
     * @return void
     */
    public function setLogger(Zend_Log $logger) 
    {
        $this-&amp;gt;_logger = $logger;
    }

    /**
     * Log something
     *
     * @param string $level
     * @param string $msg
     * @return void
     */
    protected function log($level, $msg)
    {
        if ($this-&amp;gt;_logger !== null) {
            $this-&amp;gt;_logger-&amp;gt;{$level}($msg);
        }
    }

}

/**
 * Hello World
 */
class HelloWorld
{
    use Logging;

    /**
     * Run the hello world
     */
    public function run()
    {
        $this-&amp;gt;log(&quot;info&quot;, &quot;running&quot;);
        echo &quot;Hello World!\n&quot;;
        $this-&amp;gt;log(&quot;info&quot;, &quot;done&quot;);
    }
}

/**
 * Traits demo
 */
date_default_timezone_set('Europe/London');
require_once 'Zend/Log.php';

$logger = Zend_Log::factory(array(
    array(
        'writerName'   =&amp;gt; 'Stream',
        'writerParams' =&amp;gt; array(
            'stream'   =&amp;gt; 'php://stdout',
        ),
    ),
));

$hw = new HelloWorld;
$hw-&amp;gt;setLogger($logger);
$hw-&amp;gt;run();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After downloading and compiling the latest alpha, I can run the code seeing the logging I wanted.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;davem@marajade:~$ cd src
davem@marajade:src$ tar -zxvf ~/Downloads/php-5.4.0alpha3.tar.gz
davem@marajade:src$ cd php-5.4.0alpha3
davem@marajade:php-5.4.0alpha3$ ./configure --disable-all
davem@marajade:php-5.4.0alpha3$ make
davem@marajade:php-5.4.0alpha3$ cd ~/src/traits-demo
davem@marajade:traits-demo$ ~/src/php-5.4.0alpha3/sapi/cli/php run.php 
2011-08-05T23:33:15+01:00 INFO (6): running
Hello World!
2011-08-05T23:33:15+01:00 INFO (6): done
davem@marajade:traits-demo$ 
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Copy install packages to new machine</title>
      <link>http://davedevelopment.co.uk/2011/04/19/copy-install-packages-to-new-machine.html</link>
      <pubDate>Tue, 19 Apr 2011 09:37:53 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/04/19/copy-install-packages-to-new-machine</guid>
      <description>&lt;p&gt;Note to self as much as anything, taken from http://ubuntuforums.org/showthread.php?t=261366.&lt;/p&gt;

&lt;p&gt;Old machine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; sudo dpkg --get-selections &amp;gt; installed-software
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;New Machine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; sudo dpkg --set-selections &amp;lt; installed-software
&amp;gt; sudo dselect
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Asynchronous cache priming with progress bars</title>
      <link>http://davedevelopment.co.uk/2011/04/04/asynchronous-cache-priming-with-progress-bars-via-gearman-memcache-and-dojo.html</link>
      <pubDate>Mon, 04 Apr 2011 08:09:13 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/04/04/asynchronous-cache-priming-with-progress-bars-via-gearman-memcache-and-dojo</guid>
      <description>&lt;p&gt;Bit of a long winded title, but I wanted to get it all in there.&lt;/p&gt;

&lt;p class=&quot;alert-message block-message info&quot;&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; The long
title broke my new design, so I shortened it :) &lt;/p&gt;




&lt;h4&gt;Why?&lt;/h4&gt;




&lt;ul&gt;

&lt;li&gt;I have a (highly optimised) report that takes way too long to generate, up to around 30 seconds&lt;/li&gt;
&lt;li&gt;Too many variables to prime caches for every possible combination&lt;/li&gt;
&lt;li&gt;Jakob Nielson of usability fame &lt;a href=&quot;http://www.useit.com/papers/responsetime.html&quot;&gt;says:&lt;/a&gt;
&lt;blockquote&gt;&lt;p&gt;10 seconds is about the limit for keeping the user's attention focused on the dialogue. For longer delays, users will want to perform other tasks while waiting for the computer to finish, so they should be given feedback indicating when the computer expects to be done. Feedback during the delay is especially important if the response time is likely to be highly variable, since users will then not know what to expect.&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Personally, I don't think the browsers inbuilt progress bar is enough feedback for todays web users&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;How?&lt;/h4&gt;


&lt;p&gt;First off, I configured the report to cache the generated data in &lt;a href=&quot;http://memcached.org/&quot;&gt;memcached&lt;/a&gt; for a day. That's great, now if the user requests that particular report (with the exact same combination of filters etc), twice in a day, the second time will be really snappy. What I now need is a way of priming the cache, while letting the user know what's going on. This is where &lt;a href=&quot;http://gearman.org/&quot;&gt;Gearman&lt;/a&gt; comes in handy. I've used &lt;a href=&quot;http://davedevelopment.co.uk/2009/06/01/using-message-queues-to-improve-user-experience/&quot;&gt;message queues&lt;/a&gt; in the past, but they don't have the notion of progress like a job queue does. For example purposes, I've written a little script that fetches URLs and titles from a list of RSS feeds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When memcache tells my application it can't find the droids it's looking for, my application now adds a background job to the gearman queue.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/04/screenshot1.png&quot; alt=&quot;screenshot1&quot; title=&quot;screenshot1&quot; width=&quot;535&quot; height=&quot;273&quot; class=&quot;alignleft size-full wp-image-559&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The application then forwards the user to a job status page, complete with a progress bar courtesy of the fantastic &lt;a href=&quot;http://dojotoolkit.org&quot;&gt;Dojo Toolkit&lt;/a&gt;. The user sits and watches in eager anticipation.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/04/screenshot2.png&quot; alt=&quot;screenshot2&quot; title=&quot;screenshot2&quot; width=&quot;428&quot; height=&quot;78&quot; class=&quot;alignleft size-full wp-image-560&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A gearman worker script is running on the server thanks to &lt;a href=&quot;http://supervisord.org/&quot;&gt;supervisord&lt;/a&gt;, it comes along picks the job from the queue and sets about fetching the data. As it progresses, it pings the gearman server about it's current status.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/04/screenshot3.png&quot; alt=&quot;screenshot3&quot; title=&quot;screenshot3&quot; width=&quot;579&quot; height=&quot;90&quot; class=&quot;alignleft size-full wp-image-561&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The page the user is glued to is repeatedly pinging the server to check on the progress of the job. As the job server gets updates from the worker, the web server passes them on to the user via the &lt;a href=&quot;http://docs.dojocampus.org/dijit/ProgressBar&quot;&gt;dijit.ProgressBar&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/04/screenshot31.png&quot; alt=&quot;screenshot3&quot; title=&quot;screenshot3&quot; width=&quot;464&quot; height=&quot;92&quot; class=&quot;alignleft size-full wp-image-566&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once complete, the javascript forwards the user back to the original URL, the data is successfully fetched for the cache, and we're in business.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/04/screenshot41.png&quot; alt=&quot;screenshot4&quot; title=&quot;screenshot4&quot; width=&quot;583&quot; height=&quot;541&quot; class=&quot;alignleft size-full wp-image-568&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;Get to the code already&lt;/h4&gt;


&lt;p&gt;You can browse the sample scripts at &lt;a href=&quot;https://github.com/davedevelopment/async-demo&quot;&gt;github&lt;/a&gt;, they're not amazing, just meant to show the method I've described here. As a side note, I wondered if anyone had come up with a &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt; style framework for PHP, turns out there were quite a few, I chose the &lt;a href=&quot;http://www.slimframework.com/&quot;&gt;Slim Framework&lt;/a&gt; as I could see from the homepage it took PHP 5.3 lambdas, the others didn't make it too clear.&lt;/p&gt;

&lt;p&gt;Has anyone else done anything similar? Am I doing something stupid? &lt;a href=&quot;#comments&quot;&gt;Comments&lt;/a&gt; are welcome.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Iterations plugin for Redmine</title>
      <link>http://davedevelopment.co.uk/2011/02/07/iterations-plugin-for-redmine.html</link>
      <pubDate>Mon, 07 Feb 2011 14:11:34 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2011/02/07/iterations-plugin-for-redmine</guid>
      <description>&lt;p&gt;I was impressed by the simplicity of &lt;a href=&quot;http://37signals.com/&quot;&gt;37signals&lt;/a&gt;' &lt;a href=&quot;http://37signals.com/svn/posts/2659-iterations-a-new-internal-app-for-managing-what-we-work-on-next&quot;&gt;Iterations&lt;/a&gt; when I saw their original post, it's a basic web app used to track their own internal ideas and feature requests, and also to help decide who's going to work on those features, but that was as far as I got with it, until I was reminded of it a few weeks later when listening to an episode of &lt;a href=&quot;http://techzinglive.com/&quot;&gt;techzing&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;#techzing&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;[caption id=&quot;attachment_539&quot; align=&quot;aligncenter&quot; width=&quot;529&quot; caption=&quot;More on the jabber bot later&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/02/screenshot241.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2011/02/screenshot241.png&quot; alt=&quot;More on the jabber bot later&quot; title=&quot;screenshot24&quot; width=&quot;529&quot; height=&quot;280&quot; class=&quot;size-full wp-image-539&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;I face somewhat of an uphill battle trying to encourage my staff to come up with their own ideas, initiatives and suggestions and thought something like this might help promote that kind of thing, so I set about creating a plugin for &lt;a href=&quot;http://redmine.org&quot;&gt;redmine&lt;/a&gt;, the issue tracker we use. I'm sure it's not quite as sexy as 37signals', but I'm quite happy with it and it's working out ok so far.
[caption id=&quot;attachment_541&quot; align=&quot;aligncenter&quot; width=&quot;538&quot; caption=&quot;Tracking ideas that aren't necessarily project based&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/02/screenshot25.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2011/02/screenshot25.png&quot; alt=&quot;Tracking ideas that aren't necessarily project based&quot; title=&quot;screenshot25&quot; width=&quot;538&quot; height=&quot;204&quot; class=&quot;size-full wp-image-541&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;I'm far from a skilled Rails developer, nevermind a redmine plugin developer, but if anyone would like to give the plugin a try, it's up on &lt;a href=&quot;https://github.com/davedevelopment/redmine_iterations&quot;&gt;github&lt;/a&gt;. It's been developed against the redmine trunk, so your mileage may vary, but I would appreciate anyone giving the code a once over, tidying bits up, making it more rails/redmine friendly etc, and sending me a pull request.&lt;/p&gt;

&lt;p&gt;[caption id=&quot;attachment_542&quot; align=&quot;aligncenter&quot; width=&quot;538&quot; caption=&quot;Users can comment, +1 or offer to work on an iteration&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2011/02/screenshot26.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2011/02/screenshot26.png&quot; alt=&quot;Users can comment, +1 or offer to work on an iteration&quot; title=&quot;screenshot26&quot; width=&quot;538&quot; height=&quot;321&quot; class=&quot;size-full wp-image-542&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;techzin&quot;&gt;&lt;/a&gt;&lt;sup&gt;1&lt;/sup&gt; I recently started listening to podcasts again and I was very disappointed to find out &lt;a href=&quot;http://stackoverflow.com&quot;&gt;StackOverflow&lt;/a&gt; have given up with the podcasting and &lt;a href=&quot;http://youlooknicetoday.com/&quot;&gt;You Look Nice Today&lt;/a&gt; are very few and far between, but after reading an &lt;a href=&quot;http://www.codusoperandi.com/posts/bootstrapping-with-kids&quot;&gt;inspiring blog post&lt;/a&gt;, I thought I'd give &lt;a href=&quot;http://techzinglive.com&quot;&gt;Jason's podcast&lt;/a&gt; a try. Slowly working my way through a few months worth of back catalog, quite enjoying it, worth a listen if you're into that kind of thing.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to install gitolite on Ubuntu 10.10 (Maverick Meerkat)</title>
      <link>http://davedevelopment.co.uk/2010/12/05/how-to-install-gitolite-on-ubuntu-10-10-maverick-meerkat.html</link>
      <pubDate>Sun, 05 Dec 2010 11:19:15 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2010/12/05/how-to-install-gitolite-on-ubuntu-10-10-maverick-meerkat</guid>
      <description>&lt;p&gt;&lt;img src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Git-logo.svg/71px-Git-logo.svg.png&quot; alt=&quot;Git&quot; style=&quot;float:right;margin-left:20px; margin-bottom:20px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At work we recently switched from &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;subversion&lt;/a&gt; to &lt;a href=&quot;http://git-scm.com/&quot;&gt;Git&lt;/a&gt; for our version control. I wont go into it too much, but the main reasons where:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;We wanted a distributed system, for the flexibility it offers individuals&lt;/li&gt;
    &lt;li&gt;We wanted the enhanced branch/merge&lt;/li&gt;
    &lt;li&gt;Just for fun really, broaden our horizons&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Anyway, I love &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;, but it's not the answer to everything! I wanted a central repository that I could control, so having had a brief glimpse at &lt;a href=&quot;http://gitorious.org/&quot;&gt;Gitorious&lt;/a&gt; and &lt;a href=&quot;http://eagain.net/gitweb/?p=gitosis.git&quot;&gt;gitosis&lt;/a&gt;, I settled on &lt;a href=&quot;https://github.com/sitaramc/gitolite&quot;&gt;gitolite&lt;/a&gt;. Now, I'm usually quite a lazy sys admin, and unless I desperately need a feature in the latest version of an application, I'm usually happy to fall back on the my chosen package manager, in this case &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu's&lt;/a&gt; APT. Gitolite got a package as of version 10.10 Maverick Meerkat, so I told our local Ubuntu mirror to download all the 10.10 packages and after that, upgraded the server I had in mind so that I could use the gitolite package.&lt;/p&gt;

&lt;h4&gt;Install Gitolite&lt;/h4&gt;


&lt;p&gt;Nice and easy this part, on the server:&lt;/p&gt;

&lt;pre&gt;
server&gt; sudo apt-get update
server&gt; sudo apt-get install gitolite
&lt;/pre&gt;




&lt;h4&gt;Creating a Public/Private key pair&lt;/h4&gt;


&lt;p&gt;If you already have one, send the public halve over to the server and skip this part. Otherwise, take a look at &lt;a href=&quot;http://www.debuntu.org/ssh-key-based-authentication&quot;&gt;ssh key based authentication&lt;/a&gt;, then create your key pair on your client machine:&lt;/p&gt;

&lt;pre&gt;
client&gt; ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/davem/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/davem/.ssh/id_rsa.
Your public key has been saved in /home/davem/.ssh/id_rsa.pub.
The key fingerprint is:
61:bf:f5:2d:f6:ed:cd:10:b7:0c:be:5d:4d:8f:a3:0d davem@client
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|        o        |
|       . o       |
|        S . ... o|
|           o..o*+|
|          . E.Bo=|
|             =o*+|
|            ...o*|
+-----------------+
&lt;/pre&gt;


&lt;p&gt;Once created, send the public halve to the gitolite server. Be sure to use the name you provided when creating the key. In this example, I've called the key davem.pub on the target machine, so I can differentiate between myself and other developers.&lt;/p&gt;

&lt;pre&gt;
client&gt; scp ~/.ssh/id_rsa.pub server:davem.pub
&lt;/pre&gt;




&lt;h4&gt;Configure gitolite&lt;/h4&gt;


&lt;p&gt;On the server, copy the public halve to a convenient location and run the gl-setup tool.&lt;/p&gt;

&lt;pre&gt;
server&gt; mv davem.pub /tmp/davem.pub
server&gt; chmod 666 /tmp/davem.pub
server&gt; sudo su gitolite
server&gt; gl-setup /tmp/davem.pub
...
&lt;/pre&gt;


&lt;p&gt;That's gitolite setup, we now need to go back to the client machine to fully configure it. First edit your &lt;tt&gt;.ssh/config&lt;/tt&gt; file, so that ssh knows how to connect to the server. Again, be careful to use the correct name for your key pair:&lt;/p&gt;

&lt;pre&gt;
Host servername
IdentityFile ~/.ssh/id_rsa
&lt;/pre&gt;


&lt;p&gt;Now we can clone the git repository that is used to configure gitolite:&lt;/p&gt;

&lt;pre&gt;
client&gt; git clone gitolite@server:gitolite-admin
Initialized empty Git repository in /home/davem/gitolite-admin/.git/
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
client&gt; cd gitolite-admin
&lt;/pre&gt;




&lt;h4&gt;Adding repositories&lt;/h4&gt;


&lt;p&gt;The gitolite admin contains two folders. The first, &lt;tt&gt;conf&lt;/tt&gt; contains a single config file. Open that and create a new repository by adding:&lt;/p&gt;

&lt;pre&gt;
        repo    mytest
                  RW+     =   @all
&lt;/pre&gt;


&lt;p&gt;You then need to commit the changes and push them to the gitolite server:&lt;/p&gt;

&lt;pre&gt;
client&gt; git commit -m &quot;Added mytest repo&quot; conf/gitolite.conf
client&gt; git push
&lt;/pre&gt;


&lt;p&gt;We then should be able to clone our new repository:&lt;/p&gt;

&lt;pre&gt;
client&gt; git clone gitolite@server:mytest
&lt;/pre&gt;




&lt;h4&gt;Adding users&lt;/h4&gt;


&lt;p&gt;To add a new user, simply add their public key halve to your clone of the &lt;tt&gt;gitolite-admin&lt;/tt&gt; repo, add, commit and push.&lt;/p&gt;

&lt;pre&gt;
client&gt; cd gitolite-admin
client&gt; cp ~/Downloads/another.pub keydir/
client&gt; git add keydir/another.pub
client&gt; git commit -m &quot;Added another as a user&quot; keydir/another.pub
client&gt; git push
&lt;/pre&gt;


&lt;p&gt;I wont go any further than that, you can configure fine grain access control and other things in the &lt;tt&gt;conf/gitolite.conf&lt;/tt&gt; file, check out the &lt;a href=&quot;https://github.com/sitaramc/gitolite/blob/pu/doc/2-admin.mkd&quot;&gt;documentation&lt;/a&gt;. Hope it's been helpful, comments (especially corrections) are appreciated.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Notes from porting ruby to php</title>
      <link>http://davedevelopment.co.uk/2010/11/29/notes-from-porting-ruby-to-php.html</link>
      <pubDate>Mon, 29 Nov 2010 22:13:30 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2010/11/29/notes-from-porting-ruby-to-php</guid>
      <description>&lt;p&gt;I read a nice post on &lt;a href=&quot;http://www.moserware.com/2010/10/notes-from-porting-c-code-to-php.html&quot;&gt;porting c# code to php&lt;/a&gt; a while back via &lt;a href=&quot;http://news.ycombinator.com&quot;&gt;hacker news&lt;/a&gt; and found it quite interesting. This week I've found myself in a similar situation, only reversed, I'm porting &lt;strong&gt;from&lt;/strong&gt; a language I'm not familiar with, and I'm porting code that I don't necessarily understand! I've written a couple of rails apps, but they were very basic, and I have no real clue with the delicacies of the ruby language.&lt;/p&gt;

&lt;p&gt;We've recently switched to &lt;a href=&quot;http://git-scm.com/&quot;&gt;git&lt;/a&gt; and in order to help facilitate the flexibility that git brings, I thought I'd replace the &lt;a href=&quot;http://davedevelopment.co.uk/2008/04/14/how-to-simple-database-migrations-with-phing-and-dbdeploy/&quot;&gt;database migrations system&lt;/a&gt; we currently use, predominantly to allow for 'interleaved' migrations, but the flexibility for running code as well as sql would be beneficial.&lt;/p&gt;

&lt;p&gt;We evaluated some of the existing solutions out there and unsuprisingly we settled on &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;rails'&lt;/a&gt; migrations feature set as being the best match for us. Now, I read about &lt;a href=&quot;https://github.com/thuss/standalone-migrations&quot;&gt;standalone migrations&lt;/a&gt;, but didn't really want to force our project to be dependant on another language, so decided to port &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Migration.html&quot;&gt;ActiveRecord::Migration&lt;/a&gt; to php.&lt;/p&gt;

&lt;div class=&quot;alert-message block-message warning&quot;&gt;
    &lt;strong&gt;Update 02/11/2011&lt;/strong&gt;: I've since &lt;a href=&quot;/2011/11/01/phpmig-simple-migrations-for-php.html&quot;&gt;moved on&lt;/a&gt; from this method of running migrations, checkout &lt;a href=&quot;http://github.com/davedevelopment/phpmig&quot;&gt;phpmig on github&lt;/a&gt;. It's similar to the tool I describe here, but not tied to a particular project, library or framework.
&lt;/div&gt;


&lt;p&gt;First I had to fathom out the file structure, everything seemed to be jammed into one file, so I converted that to a file structure that more closely resembled that of our application library. I also decided at this point that I wasn't going to bother with the automated reversal feature, that seems a little overkill for us. I also aren't really interested in abstracting the DDL at this point, SQL is all we need.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Spencer/
|-- Db
|   |-- Exception.php
|   |-- Migration
|   |   |-- Exception
|   |   |   |-- DuplicateName.php
|   |   |   |-- DuplicateVersion.php
|   |   |   |-- IllegalName.php
|   |   |   |-- Irreversible.php
|   |   |   `-- UnknownVersion.php
|   |   |-- Exception.php
|   |   `-- Migrator.php
|   |-- Migration.php
|   `-- MigrationProxy.php
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next I wrote the exception classes, converting something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class DuplicateMigrationVersionError &amp;lt; ActiveRecordError#:nodoc:
  def initialize(version)
    super(&quot;Multiple migrations have the version number #{version}&quot;)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Spencer_Db_Migration_Exception_DuplicateVersion extends Spencer_Db_Migration_Exception
{
    public function __construct($version)
    {
        parent::__construct(&quot;Multiple migrations have the version number $version&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That was simple enough, so then I moved on to the Migration class. This is where I hit my first roadblock and had to go learn some things about ruby meta-programming, specifically the &lt;a href=&quot;http://www.contextualdevelopment.com/articles/2008/ruby-singleton&quot;&gt;singleton class&lt;/a&gt;. Now, I'll admit I still don't fully understand it, but worked out enough to see that the main use of the singleton class was to declare class methods. However, I was quickly stumped again by this piece of code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class &amp;lt; &amp;lt; self
  attr_accessor :delegate # :nodoc:
end

def self.method_missing(name, *args, &amp;amp;block) # :nodoc:
  (delegate || superclass.delegate).send(name, *args, &amp;amp;block)
end

&amp;gt;&amp;gt;&amp;gt;&amp;gt; snip &amp;lt;&amp;lt;&amp;lt;&amp;lt;

# instantiate the delegate object after initialize is defined
self.verbose = true
self.delegate = new

def up
  self.class.delegate = self
  return unless self.class.respond_to?(:up)
  self.class.up
end

def down
  self.class.delegate = self
  return unless self.class.respond_to?(:down)
  self.class.down
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's my very uneducated take on it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We declare delegate as a class member.&lt;/li&gt;
&lt;li&gt;We then override ruby's built in &lt;a href=&quot;http://ruby-doc.org/core/classes/Kernel.html#M005925&quot;&gt;method_missing&lt;/a&gt; method, which will handle any messages sent to this class that it doesn't understand.&lt;/li&gt;
&lt;li&gt;Set the verbose class member to true and the delegate member to a new instance of ActiveRecord::Migration, although I'm not too sure on the latter&lt;/li&gt;
&lt;li&gt;Define two method instance methods, that set the delegate class member to the current instance, then call the same method on the class, which will delegate it to the instance we set as the delegate? - This just doesn't make sense to me, but maybe it's not supposed to? These are the two methods that the migrations themselves override&lt;/li&gt;

&lt;/ol&gt;


&lt;p&gt;So anyway, I simply skipped that bit. I figured it would dawn on me what it was all for when I came to need it!&lt;/p&gt;

&lt;p&gt;The next point of interest was the little &lt;a href=&quot;http://ruby-doc.org/stdlib/libdoc/benchmark/rdoc/classes/Benchmark.html#M000004&quot;&gt;Benchmark::measure&lt;/a&gt; method, which uses ruby's &lt;a href=&quot;http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html&quot;&gt;yield&lt;/a&gt; statement to measure the time taken to run a method. The method itself is passed as an argument to the method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time = Benchmark.measure { send(direction) }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Benchmark.measure method then records some times, runs the passed method by calling the yield statement, then records the finish times and returns them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# File benchmark.rb, line 291
def measure(label = &quot;&quot;) # :yield:
  t0, r0 = Benchmark.times, Time.now
  yield
  t1, r1 = Benchmark.times, Time.now
  Benchmark::Tms.new(t1.utime  - t0.utime, 
                     t1.stime  - t0.stime, 
                     t1.cutime - t0.cutime, 
                     t1.cstime - t0.cstime, 
                     r1.to_f - r0.to_f,
                     label)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I couldn't replicate this exactly using PHP, but the new &lt;a href=&quot;http://php.net/manual/en/functions.anonymous.php&quot;&gt;closures&lt;/a&gt; available in PHP 5.3 made it relatively neat. I don't know of any way to measure cpu/user/real time in PHP, so I ended up simply with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static function measure(Closure $function)
{
    $time = microtime(1);
    $function();
    return new Spencer_Benchmark_Tms(microtime(1) - time());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code to call it needs a little more explaining, the &lt;tt&gt;use&lt;/tt&gt; keyword specifies variables from the parent scope that the closure can access.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$th = $this;
$time = Spencer_Benchmark::measure(function() use ($th, $direction) { $th-&amp;gt;$direction(); });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mimicking the Activerecord::MigrationProxy class was easy enough, then I moved on to the Activerecord::Migrator class. Now, the first problem I had was the use of method names in this class. Because of the aforementioned singleton class, ruby classes can effectively have both a class method and an instance method with the same name, which PHP can't. To keep track, I prefixed the instance methods with 'really' (not the best choice, but once I had started I thought it best to stick with it). Although it worked, it proved very difficult to keep track of as I was porting the code over. The next thing I noticed about ruby was how nice it was to be working with objects all the time. Using methods like &lt;a href=&quot;http://ruby-doc.org/core/classes/Enumerable.html#M003128&quot;&gt;Enumerable.map&lt;/a&gt; and &lt;a href=&quot;http://ruby-doc.org/core/classes/Enumerable.html#M003123&quot;&gt;Enumerable.detect&lt;/a&gt; just seems a little nicer than my own versions mangled up in PHP. Take the following code, that fetches a set of records from the database, uses map to convert the array of objects returned into an array of integers and then sorts it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def get_all_versions
  table = Arel::Table.new(schema_migrations_table_name)
  Base.connection.select_values(table.project(table['version']).to_sql).map{ |v| v.to_i }.sort
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My PHP equivalent gets the job done, but simply doesn't look as elegant, despite me cheating and using the SQL to sort the data. The &lt;a href=&quot;http://www.php.net/manual/en/spl.iterators.php&quot;&gt;SPL Iterators&lt;/a&gt; can run sorts with a user defined function, but I can't see map and detect etc.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static function getAllVersions()
{
    try {
        $table = self::getDbTable();
        $rows = $table-&amp;gt;fetchAll($table-&amp;gt;select()-&amp;gt;from($table, array('version'))-&amp;gt;order('version ASC'))-&amp;gt;toArray();
        return array_map(function($r) { return $r['version'];}, $rows);
    } catch (Exception $e) {
        return array();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This seemed like a recurring theme as I ported the rest of &lt;tt&gt;Migrator&lt;/tt&gt;, with the use of closures/blocks at every corner. Other than that, I didn't really have any problems. I skipped the DDL transactions, as, as far as I know, MySQL doesn't support them.&lt;/p&gt;

&lt;p&gt;I'd then finished the library, so I took a look inside the rails rake tasks that are used to run the migrations. Thankfully, they were nice and simple and mostly called the nice class methods I'd already ported over to PHP. I've previously used &lt;a href=&quot;http://phing.info&quot;&gt;phing&lt;/a&gt; for tasks like this, but I thought I'd give &lt;a href=&quot;http://framework.zend.com/manual/en/zend.tool.html&quot;&gt;Zend_Tool&lt;/a&gt; a go. First, I'm not so keen on the way Zend_Tool integrates into a project. It needs a big fat XML file to work nicely, but that xml file can't be generated from existing code, so doesn't play well with a team of developers. Secondly, the zf command line program doesn't really tie in to your codebase at all. Ideally for me, the migration classes shouldn't need to worry about bootstrapping the application, so I copied the zf.php file to our codebase and customised it to bootstrap our application and also set the include path up for the custom provider I was about to write. An hour later and I had a nice Zend_Tool provider, that nicely generate, ran and provided status on migrations.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;davem@CSL2717:[develop]sos$ ./zf ? migration
Zend Framework Command Line Console Tool v1.10.7
Actions supported by provider &quot;Migration&quot;
  Migration
    zf status migration
    zf migrate migration version
    zf redo migration verison
    zf up migration version
    zf down migration version
    zf forward migration steps[=1]
    zf rollback migration steps[=1]
    zf generate migration name


davem@CSL2717:[develop]sos$ ./zf generate migration FirstMigration
Created migration at 20101129205655_first_migration.php

davem@CSL2717:[develop]sos$ vim db/migrations/20101129205655_first_migration.php 
davem@CSL2717:[develop]sos$ ./zf status migration

 Status   Migration ID    Migration Name
--------------------------------------------------
   down  20101129205655  FirstMigration


davem@CSL2717:[develop]sos$ ./zf migrate migration
== 20101129205655 FirstMigration: migrating ===================================
== 20101129205655 FirstMigration: migrated 0.3273s ============================

davem@CSL2717:[develop]sos$ ./zf status migration

 Status   Migration ID    Migration Name
--------------------------------------------------
     up  20101129205655  FirstMigration


davem@CSL2717:[develop]sos$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code isn't really in any state to be published, needs a lot of polishing, but once that's done, I'll have a word with my bosses and maybe sling it up on github.&lt;/p&gt;

&lt;p&gt;In conclusion, I can see while all the ruby fanboys become fanboys, but while it doesn't always look as pretty, php still gets things done for me.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ZFSnippets.com now managed by bescript.de</title>
      <link>http://davedevelopment.co.uk/2010/06/01/zfsnippets-com-now-managed-by-bescript-de.html</link>
      <pubDate>Tue, 01 Jun 2010 13:18:41 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2010/06/01/zfsnippets-com-now-managed-by-bescript-de</guid>
      <description>&lt;p&gt;&lt;a href=&quot;/2010/04/26/wanted-new-home-for-zfsnippets-com/&quot;&gt;Not so long ago&lt;/a&gt;, I posted
requesting that people who fancied maintaining
&lt;a href=&quot;http://zfsnippets-com&quot;&gt;ZFSnippets.com&lt;/a&gt; should get in touch and see if I could
hand it over. Thanks to everyone who volunteered (sorry I didn't get back to you
all individually!) and eventually I decided to hand it over to German PHP
outfit, &lt;a href=&quot;http://www.bescript.de&quot;&gt;bescript.de&lt;/a&gt;. &lt;a href=&quot;http://twitter.com/psaxde&quot;&gt;Ben&lt;/a&gt;
was very clear and excited in his email and after discussing it with him I knew
the handover would be nice and easy and bescript.de would take good care of the
site. They have already &lt;a href=&quot;http://blog.zfsnippets.com/new-features-and-changes/&quot;&gt;added new
features&lt;/a&gt; and ticked some
items off the uservoice list!&lt;/p&gt;

&lt;p&gt;Again, thanks to everyone who got in touch and best of luck to Ben and his team with the site.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Set MySQL connection variables with mysql-proxy</title>
      <link>http://davedevelopment.co.uk/2010/06/01/set-mysql-connection-variables-with-mysql-proxy.html</link>
      <pubDate>Tue, 01 Jun 2010 11:01:02 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2010/06/01/set-mysql-connection-variables-with-mysql-proxy</guid>
      <description>&lt;p&gt;We recently moved the application I work on everyday to &lt;a href=&quot;http://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt; and bravely adopted their &lt;a href=&quot;http://aws.amazon.com/rds/&quot;&gt;Relational Database Service (RDS)&lt;/a&gt; and have had little trouble thus far, but the other day I noticed since we kicked into BST, timestamps in the database where an hour behind. Low and behold, the default time zone &lt;a href=&quot;http://aws-musings.com/amazon-relational-database-service-rds-the-timezone-problem/&quot;&gt;cannot be changed&lt;/a&gt;. Luckily, we've been using &lt;a href=&quot;https://launchpad.net/mysql-proxy&quot;&gt;mysql-proxy&lt;/a&gt; since we migrated and rather than changed our application, I managed to knock up a &lt;a href=&quot;http://www.lua.org/&quot;&gt;lua&lt;/a&gt; script that sets the timezone variable on every query. It would be nice if it could do it when it creates a connection, but I've not worked out how to do that yet!&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;lua&quot;&gt;
---
-- read_query() can rewrite packets
--
function read_query( packet )
        if string.byte(packet) == proxy.COM_QUERY then
                proxy.queries:append(1, string.char(proxy.COM_QUERY) .. &quot;SET time_zone = 'Europe/London'&quot;, {resultset_is_needed = true})
                proxy.queries:append(2, packet)
                return proxy.PROXY_SEND_QUERY
        end
end

---
-- read_query_result() is called when we receive a query result
-- from the server
--
function read_query_result(inj)
        if (inj.type == 1) then
            return proxy.PROXY_IGNORE_RESULT
        end
end

&lt;/pre&gt;


&lt;p&gt;If anyone could point me in the general direction for setting the variable at connection time, it'd be appreciated. I assume I can create a create_connection function, but I don't know where to go from there.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Wanted: New home for zfsnippets.com</title>
      <link>http://davedevelopment.co.uk/2010/04/26/wanted-new-home-for-zfsnippets-com.html</link>
      <pubDate>Mon, 26 Apr 2010 10:58:22 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2010/04/26/wanted-new-home-for-zfsnippets-com</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update 27/04/2010:&lt;/strong&gt; I have received a number of enquiries via email and I'll be going through them to try and find the best candidate, I'll also make an effort to reply to all emails I've received. Thanks to all for your interest.&lt;/p&gt;

&lt;p&gt;It's been just over a year since I &lt;a href=&quot;http://davedevelopment.co.uk/2009/03/04/zfsnippetscom-zend-framework-code-snippets/&quot;&gt;initially launched&lt;/a&gt; &lt;a href=&quot;http://zfsnippets.com&quot;&gt;zfsnippets.com&lt;/a&gt;, it was a good little project for me to get used to the Zend Framework, but since then I've totally neglected it. I'd normally leave a website going despite my lack of enthusiasm, but I no longer need the VPS it is hosted on so I'm looking for someone else to take the project on and move to their hosting solution.&lt;/p&gt;

&lt;p&gt;My interests have moved quite rapidly in the last year and the project is sadly no longer of interest to me. ZFSnippets receives approximately 2,500 visits a month, so I think it's worth keeping the project alive.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2010/04/screenshot2.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2010/04/screenshot2-300x154.png&quot; alt=&quot;screenshot2&quot; title=&quot;screenshot2&quot; width=&quot;300&quot; height=&quot;154&quot; class=&quot;alignleft size-medium wp-image-472&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're interested in hosting the site and hopefully building on it and improving it, please email me, dave.marshall &lt;em&gt;at&lt;/em&gt; atstsolutions.co.uk.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Review: Zend Framework 1.8 Web Application Development</title>
      <link>http://davedevelopment.co.uk/2010/02/11/review-zend-framework-1-8-web-application-development.html</link>
      <pubDate>Thu, 11 Feb 2010 14:51:24 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2010/02/11/review-zend-framework-1-8-web-application-development</guid>
      <description>&lt;p&gt;&lt;a style=&quot;margin:0px 10px 10px 0px;float:left&quot; href=&quot;http://www.packtpub.com/symfony-1-3-web-application-development?utm_source=shift-up.de&amp;utm_medium=bookrev&amp;utm_content=blog&amp;utm_campaign=mdb_001213&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2010/02/Zend-book-image.jpg&quot; alt=&quot;Zend book image&quot; title=&quot;Zend book image&quot; width=&quot;100&quot; height=&quot;123&quot; class=&quot;alignleft size-full wp-image-441&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometime last year, I, along with &lt;a href=&quot;http://devzone.zend.com/article/11398&quot;&gt;quite&lt;/a&gt; &lt;a href=&quot;http://blog.fedecarg.com/2009/12/11/review-zend-framework-1-8-web-application-development/&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;http://raphaelstolt.blogspot.com/2009/10/zend-framework-18-web-application.html&quot;&gt;few&lt;/a&gt; &lt;a href=&quot;http://net.tutsplus.com/articles/reviews/book-review-zend-framework-1-8-web-application-development/&quot;&gt;others&lt;/a&gt;, was asked to review one of 
&lt;a href=&quot;http://www.packtpub.com/&quot;&gt;Packt Publishing&lt;/a&gt;'s new books, &lt;a href=&quot;http://www.packtpub.com/zend-framework-1-8-web-application-development?utm_source=davedevelopment.co.uk&amp;utm_medium=bookrev&amp;utm_content=blog&amp;utm_campaign=mdb_001551&quot;&gt;Zend Framework 1.8 Web Application Development&lt;/a&gt;, written by &lt;a href=&quot;http://thepopeisdead.com/&quot;&gt;Keith Pope&lt;/a&gt;. They sent me a copy, which was very good of them and although it's taken me ages to finish and get round to writing this review, that's not a true reflection of how good the book was, I'm just a very busy/lazy person! So lazy, that I did in fact say I'd have it done in two weeks, which turned into 4 months.&lt;/p&gt;




&lt;blockquote cite=&quot;http://davedevelopment.co.uk/2009/10/15/zend-framework-1-8-web-application-development/&quot;&gt;&lt;p&gt;Packt asked if I'd be interested in reviewing the book, so watch this space, I'll be back in a couple of weeks with a review. &lt;/p&gt;&lt;/blockquote&gt;


&lt;p style=&quot;text-align:right;margin-top:-3px;padding-top:0px;font-size:90%&quot;&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2009/10/15/zend-framework-1-8-web-application-development/&quot;&gt;My Post dated 15/10/2009&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;Introduction&lt;/h2&gt;


&lt;p&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Design, develop, and deploy feature-rich PHP web applications with this MVC framework&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;That is the books strap line, and it does exactly what it says on the tin. The bulk of the book actually takes you through the design, development, testing and deployment of a &lt;strong&gt;real world example application&lt;/strong&gt;, called the Storefront. The book claims that it is written for PHP web developers that are either using or looking to start using the &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; and that a basic knowledge of Object Oriented design would be helpful. While you might be able to manage without any OOD experience, I'd say you definitely need some to get the most out of this book, as the second chapter digs right under the hood of the Frameworks &lt;strong&gt;MVC architecture&lt;/strong&gt;. My personal experience was that I got to learn all the things I haven't had time to learn, I've been using the Framework for a couple of years now, always appreciating, but not always &lt;strong&gt;understanding&lt;/strong&gt; what it was doing for me. &lt;/p&gt;




&lt;h2&gt;MVC Architecture&lt;/h2&gt;




&lt;p&gt;The first chapter gives you a &lt;strong&gt;brief overview &lt;/strong&gt;of creating an MVC application in the Zend Framework, experienced users of the Framework will probably want to gloss over this part, whereas people looking to start using the framework should take their time and take things in. The next chapter is when I really started to enjoy the book. Each &lt;strong&gt;component&lt;/strong&gt; of the MVC architecture is presented as it's own topic, with each component getting a breakdown of Design Patterns/theory, default settings/configuration, usage and finally customisation.
&lt;/p&gt;




&lt;p&gt;The chapter is well put together and considering the amount of information portrayed, is &lt;strong&gt;not overwhelming&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;Storefront Application&lt;/h2&gt;




&lt;p&gt;The rest of the book provides the information you need about the framework around a real world example application, called StoreFront, which is a basic e-commerce application. I should point out that I didn't code the application as I went, if I'm reading I like to read, but where appropriate I have used the book as a reference when updating my existing Zend Framework applications.&lt;/p&gt;




&lt;p&gt;The best thing about these chapters though, is some of the &lt;strong&gt;design theory&lt;/strong&gt; you pick up on the way, that isn't directly relevant to the Zend Framework, but can be applied to any framework out there. Best practices such as &lt;a href=&quot;http://davedevelopment.co.uk/2008/06/17/fat-models-and-the-data-access-layer/&quot;&gt;Fat Models&lt;/a&gt;, &lt;a href=&quot;http://martinfowler.com/bliki/AggregationAndComposition.html&quot;&gt;Composition&lt;/a&gt;, &lt;a href=&quot;http://www.martinfowler.com/bliki/FluentInterface.html&quot;&gt;Fluent interfaces&lt;/a&gt; are all explained in detail, along with &lt;strong&gt;relevant and realistic examples&lt;/strong&gt;. Further more, the applications MVC separation is excellent, taken in context (it might be a little overkill for the example application, but is there to show you the methods).&lt;/p&gt;




&lt;p&gt;After taking you through the creation of the application, the book then takes you into optimisation and testing. The optimisation takes you though some general &lt;strong&gt;PHP optimisation techniques&lt;/strong&gt;, but then ploughs into techniques like a transparent abstract cache that is applied to the models. Testing is carried out with the trusty &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt;, along with the frameworks extension of the library &lt;a href=&quot;http://framework.zend.com/manual/en/zend.test.html&quot;&gt;Zend_Test&lt;/a&gt; and the book goes on to integrate the test suites with &lt;a href=&quot;http://ant.apache.org/&quot;&gt;apache ant&lt;/a&gt; (why not &lt;a href=&quot;http://phing.info&quot;&gt;phing&lt;/a&gt;) and &lt;a href=&quot;http://phpundercontrol.org/&quot;&gt;phpundercontrol&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;Conclusion&lt;/h2&gt;




&lt;p&gt;In conclusion, I thought this book was &lt;strong&gt;an excellent read&lt;/strong&gt; and I plan to follow it through again when I build my next ZF app (I have two good ideas in the pipeline).  &lt;a href=&quot;http://www.packtpub.com/zend-framework-1-8-web-application-development?utm_source=davedevelopment.co.uk&amp;utm_medium=bookrev&amp;utm_content=blog&amp;utm_campaign=mdb_001551&quot;&gt;Find out more &lt;del datetime=&quot;2010-02-11T14:39:50+00:00&quot;&gt;or&lt;/del&gt; and buy it!&lt;/a&gt;. Thanks to Packt for sending me a copy!&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Zend Framework 1.8 Web Application Development</title>
      <link>http://davedevelopment.co.uk/2009/10/15/zend-framework-1-8-web-application-development.html</link>
      <pubDate>Thu, 15 Oct 2009 08:55:04 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/10/15/zend-framework-1-8-web-application-development</guid>
      <description>&lt;p&gt;&lt;img src=&quot;https://www.packtpub.com/images/PacktLogoSmall.png&quot; style=&quot;margin:0px
10px 10px 0px;float:left&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.packtpub.com/&quot;&gt;Packt Publishing&lt;/a&gt;
 have recently contacted me letting me know about one of their new
books, &lt;a href=&quot;http://www.packtpub.com/zend-framework-1-8-web-application-development/book&quot;&gt;Zend Framework 1.8 Web Application Development&lt;/a&gt;
. It looks reasonably priced, and
if you fancy having a quick look before you by, the author
&lt;a href=&quot;http://www.thepopeisdead.com&quot;&gt;Keith Pope&lt;/a&gt; has a &lt;a href=&quot;http://www.thepopeisdead.com/main/comments/free_chapter_and_more_to_come/&quot;&gt;free chapter&lt;/a&gt;
 to download. Packt asked if I'd be interested in reviewing the book,
so watch this space, I'll be back in a couple of weeks with a review.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Zend Framework Poster</title>
      <link>http://davedevelopment.co.uk/2009/08/21/zend-framework-poster.html</link>
      <pubDate>Fri, 21 Aug 2009 11:18:59 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/08/21/zend-framework-poster</guid>
      <description>&lt;p&gt;After stumbling across an offer for a &lt;a href=&quot;http://blog.thinkphp.de/archives/399-Mayflower-loves-Zend-Framework.html&quot;&gt;free Zend Framework Poster&lt;/a&gt; some time ago, I quickly dropped &lt;a href=&quot;http://mayflower.de&quot;&gt;Mayflower&lt;/a&gt; an email.&lt;/p&gt;

&lt;p&gt;Some time passed, and now it's here at work, placed next to our all important tea, coffee and biscuits station.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/08/Mayflower-poster.jpg&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/08/Mayflower-poster-300x199.jpg&quot; alt=&quot;Mayflower poster&quot; title=&quot;Mayflower poster&quot; width=&quot;300&quot; height=&quot;199&quot; class=&quot;alignnone size-medium wp-image-430&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's A0, covers nearly all of the major components and is well worth having! Top props to guys over there for pushing the &lt;a href=&quot;http://framework.zend.com&quot;&gt;Zend Framework&lt;/a&gt; like this. Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Mozilla's Content Security Policy (CSP)</title>
      <link>http://davedevelopment.co.uk/2009/06/30/mozillas-content-security-policy-csp.html</link>
      <pubDate>Tue, 30 Jun 2009 09:53:04 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/06/30/mozillas-content-security-policy-csp</guid>
      <description>&lt;p&gt;I saw &lt;a href=&quot;http://blog.mozilla.com/security/2009/06/19/shutting-down-xss-with-content-security-policy/&quot;&gt;this post&lt;/a&gt; via &lt;a href=&quot;http://slashdot.org&quot;&gt;SlashDot&lt;/a&gt; and can't help but think it's a little overkill?&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;a href=&quot;http://people.mozilla.org/~bsterne/content-security-policy/&quot;&gt;Content Security Policy&lt;/a&gt; is intended to mitigate a large class of Web Application Vulnerabilities: Cross Site Scripting. Cross Site Request Forgery has also become a large scale problem in Web Application Security, though it is not a primary focus of Content Security Policy.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;In an ideal world, this would be great, but getting all the browsers on board and implemented may take a while. I was thinking about this the other day and I don't see why the browsers/w3c can't standardise on some sort of tag or conditional comments that says don't execute any script in here. This would be simple to use and surely simple to implement. Browsers already know what to do with &lt;a href=&quot;http://www.w3schools.com/TAGS/tag_noscript.asp&quot;&gt;&lt;code&gt;&amp;lt;noscript&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Example:&lt;/p&gt;

&lt;pre class=&quot;php&quot; name=&quot;code&quot;&gt;
&amp;lt;dontexecutescript&amp;gt;
    &amp;lt;?php echo $this-&amp;gt;escape($userProvidedContent);?&amp;gt;
&amp;lt;/dontexecutescript&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Or:&lt;/p&gt;

&lt;pre class=&quot;php&quot; name=&quot;code&quot;&gt;
&amp;lt;!--[dontexecutescript] --&amp;gt;
    &amp;lt;?php echo $this-&amp;gt;escape($userProvidedContent);?&amp;gt;
&amp;lt;!--[dontexecutescript]--&amp;gt;
&lt;/pre&gt;


&lt;p&gt;I'm no expert on &lt;a href=&quot;http://en.wikipedia.org/wiki/Cross-site_scripting&quot;&gt;XSS&lt;/a&gt;, but I'm pretty sure this would solve most of the issues encountered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Okay, so one obvious problem might be that the &lt;code&gt;$userProvidedContent&lt;/code&gt; contains a closing &lt;code&gt;&amp;lt;/dontexecutescript&amp;gt;&lt;/code&gt; tag, but that's just semantics. Unique identifiers for each block, ignoring tags that don't match up, these browser developers are clever, they could come up with something.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using message queues to improve user experience</title>
      <link>http://davedevelopment.co.uk/2009/06/01/using-message-queues-to-improve-user-experience.html</link>
      <pubDate>Mon, 01 Jun 2009 13:22:48 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/06/01/using-message-queues-to-improve-user-experience</guid>
      <description>&lt;p&gt;A major part of the application I develop on my day job is a big &lt;a href=&quot;http://en.wikipedia.org/wiki/Document_management_system&quot;&gt;&lt;abbr title=&quot;Document Management System&quot;&gt;DMS&lt;/abbr&gt;&lt;/a&gt;, part of which is the ability to distribute documents to staff and external parties. The distribution system works in such a way that, if sending a document to 300 people, there will actually be 300 individual emails created, rather than one email with a list of recipients. This is desired behavior. My problem is, sending 300 emails at the click of a button can take a little time, degrading the experience for the users. This portion of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Call_graph&quot;&gt;call graph&lt;/a&gt; shows sending to just five people was taking 1+ seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/06/screenshot2.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/06/screenshot2.png&quot; alt=&quot;screenshot2&quot; title=&quot;screenshot2&quot; width=&quot;299&quot; height=&quot;180&quot; class=&quot;alignnone size-full wp-image-412&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To solve this, I started out to implement a simple &lt;a href=&quot;http://en.wikipedia.org/wiki/Queue_(data_structure)&quot; title=&quot;Read about queues on WikiPedia&quot;&gt;queuing&lt;/a&gt; system, whereby the distribution requests are added to a queue, before being sent out by a scheduled task.&lt;/p&gt;

&lt;p&gt;Rather than refactor a lot of code and do this some fancy way, I quickly put in a solution that proved the concept and seems to work pretty well for now, with minimal effort. As an example (our code's slightly more complex, I don't get paid for nothing), here's what I started with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt; ?php
class EmailSender {
    /**
     * Takes an array of addresses and sends an email to each one.
     *
     * @param array $address
     */
    public static function sendEmails($address) {
        /**
         * Code in here
         */
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The idea was fairly simple and I'm sure it's been done many times before. First step was to rename the existing method and make it private. I then wrote a new method, that checked to see if there was a queue available, if so adds the request to the queue, otherwise calls the old method. Then all I had to do was write a method that checks the queue, running any requests it finds through the original method. We've recently adopted the &lt;a href=&quot;http://framework.zend.com/&quot; title=&quot;Zend Framework&quot;&gt;Zend Framework&lt;/a&gt;, so checking out &lt;a href=&quot;http://framework.zend.com/wiki/display/ZFPROP/Zend_Queue+-+Justin+Plock&quot;&gt;Zend_Queue&lt;/a&gt; from the &lt;a href=&quot;http://framework.zend.com/svn/framework/standard/incubator/&quot; title=&quot;Zend Framework Incubator&quot;&gt;incubator&lt;/a&gt;, reading some documentation with my &lt;a href=&quot;http://www.docbook.org/&quot;&gt;docbook&lt;/a&gt; goggles on (couldn't be bothered to build it) and it was pretty much in place.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
/**
 * Zend_Queue offline processing hack example
 *
 * @author      Dave Marshall 
 * @version     $Rev: $
 * @since       $Date: $
 * @link        $URL: $
 */
class EmailSender {

    private static $queue = null;

    /**
     * Set Queue
     *
     * @param Zend_Queue $queue
     */
    public static function setQueue($queue)
    {
        self::$queue = $queue;
    }

    /**
     * Takes an array of addresses and sends an email to each one.
     *
     * @see reallySendEmail
     * @see sendQueuedEmails
     * @param array $address
     */
    public static function sendEmail($address)
    {
        if (self::$queue === null) {
            return self::reallySendEmail($address);
        }

        self::$queue-&amp;gt;send(serialize(func_get_args()));
    }

    /**
     * Takes an array of addresses and sends an email to each one.
     *
     * @see sendEmail
     * @param array $address
     */
    private static function reallySendEmail($address) 
    {
        /**
         * Code in here
         */
        echo 'Sending email to ' . implode(', ', $address) . PHP_EOL;
    }

    /**
     * Reads emails from the queue and sends them
     *
     * @param int $count - The number of queued items to process
     */
    public static function sendQueuedEmails($count)
    {
        /**
         * Should really check the queue is good here
         */

        $messages = self::$queue-&amp;gt;receive(intval($count));
        foreach($messages as $msg) {
            $args = unserialize($msg-&amp;gt;body);
            call_user_func_array(array(__CLASS__, 'reallySendEmail'), $args);
            self::$queue-&amp;gt;deleteMessage($msg);
        }
    }
}


set_include_path(
    dirname(__FILE__) . '/src/Zend_Framework/library' . PATH_SEPARATOR
    . dirname(__FILE__) . '/src/ZendI/library' . PATH_SEPARATOR
    . get_include_path()
);

require_once &quot;Zend/Loader.php&quot;;
Zend_Loader::registerAutoload();

define('DB_SERVER', 'localhost');
define('DB_PORT', 3306);
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_NAME', 'queue_example');

/**
 * Transmittal Queue
 *                   
 */
$config = array(
    'name' =&amp;gt; 'transmittal',
    'driverOptions' =&amp;gt; array(
        'host'     =&amp;gt; DB_SERVER,
        'port'     =&amp;gt; DB_PORT,
        'username' =&amp;gt; DB_USER,
        'password' =&amp;gt; DB_PASS,
        'dbname'   =&amp;gt; DB_NAME,
        'type'     =&amp;gt; 'pdo_mysql'
    )
);

// Create a database queue
$queue = new Zend_Queue('Db', $config);
$queue-&amp;gt;createQueue('myqueue'); // called for good measure

EmailSender::setQueue($queue);

/**
 * Usage for adding to the queue
 */
EmailSender::sendEmail(array('davemastergeneral@gmail.com'));

/**
 * Usage for scheduled task
 */
EmailSender::sendQueuedEmails(5);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This may not be the best practice in the world, but it &lt;a href=&quot;http://davedevelopment.co.uk/2007/07/10/getting-things-done/&quot;&gt;got the job done&lt;/a&gt;
Check it out at &lt;a href=&quot;http://www.zfsnippets.com/snippets/view/id/60&quot;&gt;ZFSnippets.com&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Redmine Issue Tracker/Project Management</title>
      <link>http://davedevelopment.co.uk/2009/04/20/review-redmine-issue-trackerproject-management.html</link>
      <pubDate>Mon, 20 Apr 2009 15:30:42 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/04/20/review-redmine-issue-trackerproject-management</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.redmine.org/&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/01/redmine_logo_bw.png&quot; alt=&quot;redmine_logo_bw&quot; title=&quot;redmine_logo_bw&quot; width=&quot;459&quot; height=&quot;235&quot; class=&quot;alignnone size-full wp-image-291&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We recently started using &lt;a href=&quot;http://www.redmine.org&quot; title=&quot;Redmine&quot;&gt;Redmine&lt;/a&gt; as our issue tracking software and we're very pleased with it. I trialled several alternatives, both open source and commercial, including &lt;a href=&quot;http://www.atlassian.com/software/jira/&quot;&gt;Jira&lt;/a&gt;, &lt;a href=&quot;http://www.fogcreek.com/FogBUGZ/&quot;&gt;FogBugz&lt;/a&gt;, &lt;a href=&quot;http://www.mantisbt.org/&quot;&gt;Mantis&lt;/a&gt; and &lt;a href=&quot;http://trac.edgewall.org/&quot;&gt;Trac&lt;/a&gt;, but decided on Redmine. Jira and FogBugz look like excellent products, but I don't feel we would use the extra functionality that warrants the price tag. Mantis looks a bit dated and although it's been a while, last time I tried to install and configure Trac, it was a bit of a nightmare.&lt;/p&gt;




&lt;p&gt;First thing first, here are some of our requirements for an issue tracker:&lt;/p&gt;




&lt;ul&gt;
    &lt;li&gt;Multiple Projects&lt;/li&gt;
    &lt;li&gt;Time tracking&lt;/li&gt;
    &lt;li&gt;Notifications (email, rss, im etc.)&lt;/li&gt;
    &lt;li&gt;Wiki&lt;/li&gt;
    &lt;li&gt;SCM integration&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Redmine does all of this and a little more, but we haven't used the other features that much. It does what we want really well, so that's good enough for us.&lt;/p&gt;




&lt;h4&gt;What I like&lt;/h4&gt;




&lt;p&gt;Editing issues in bulk is fantastic. We deploy our application fairly casually, and when we do we set all the issues that have been deployed as closed and assign them a version number. Highlight the issues, right click and set the version number.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot-1.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot-1-300x275.png&quot; alt=&quot;screenshot-1&quot; title=&quot;screenshot-1&quot; width=&quot;300&quot; height=&quot;275&quot; class=&quot;alignnone size-medium wp-image-382&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SCM integration does all we need it to. If we add Fixes #500 or Implements #500 to a commit message, issue 500 will be set to resolved and 100% complete and the revision number and commit message appears on the issue's page. Alternatively, just putting Refs #500 will show the revision number and commit message in the page, without changing the status.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot21.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot21.png&quot; alt=&quot;screenshot21&quot; title=&quot;screenshot21&quot; width=&quot;461&quot; height=&quot;120&quot; class=&quot;alignnone size-full wp-image-400&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Issues themselves can have custom fields, but we don't use them all that much. We do make lots of use of the descriptions and notes as they both take wiki markup, meaning we can enter rich text including source code highlighting and images, linking to changesets, wiki pages, target versions, source code and other issues. I like the ability to embed screenshots and call graphs in issues.&lt;/p&gt;




&lt;h4&gt;What I don't like&lt;/h4&gt;




&lt;p&gt;Here's a couple of things that bother me, if I shift my arse I might look into creating patches for the simple ones.&lt;/p&gt;




&lt;p&gt;No API! It would be really nice to have an API and there's one in &lt;a href=&quot;http://www.redmine.org/issues/296&quot;&gt;the works&lt;/a&gt;, but it's sounds like it's a bit of a ballache changing fat controllers into &lt;a href=&quot;http://davedevelopment.co.uk/2008/06/17/fat-models-and-the-data-access-layer/&quot;&gt;fat models&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;I often wish a few more items where 'clickable'. For instance when viewing the issue list, I'd like to be able to click the Category name in one of the rows and see a list of issues for that category. &lt;/p&gt;




&lt;p&gt;You can save filters on the issue list, which is ace, but it would be nice if you can 'save as new'. I often create lots of very similar queries and have to build up each one from scratch.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Rev=Canonical and all that Jazz</title>
      <link>http://davedevelopment.co.uk/2009/04/15/revcanonical-and-all-that-jazz.html</link>
      <pubDate>Wed, 15 Apr 2009 11:58:29 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/04/15/revcanonical-and-all-that-jazz</guid>
      <description>&lt;p&gt;If anybody missed it, the last few days has seen &lt;a href=&quot;http://search.twitter.com/search?q=%23revcanonical&quot;&gt;plenty of buzz&lt;/a&gt; around a &lt;a href=&quot;http://revcanonical.appspot.com/&quot;&gt;new proposal&lt;/a&gt; on how to solve the &lt;a href=&quot;http://joshua.schachter.org/2009/04/on-url-shorteners.html&quot;&gt;problem with URL shorteners&lt;/a&gt;. I kind of got lost in all the different methods and proposals people are &lt;a href=&quot;http://benramsey.com/archives/a-revcanonical-rebuttal/&quot;&gt;discussing&lt;/a&gt;, &lt;a href=&quot;http://shiflett.org/blog/2009/apr/a-rev-canonical-http-header&quot;&gt;suggesting&lt;/a&gt; or &lt;a href=&quot;http://simonwillison.net/2009/Apr/11/revcanonical/&quot;&gt;implementing&lt;/a&gt;, but I went ahead and added some simple logic to &lt;a href=&quot;http://lnkd.in&quot;&gt;lnkd.in&lt;/a&gt;, to do a HTTP HEAD request to the given URL, looking for headers in a couple of the formats suggested. I figured that was going to get out of date pretty quickly, so I modified it to use the &lt;a href=&quot;http://revcanonical.appspot.com/api&quot;&gt;RevCanonical API&lt;/a&gt;, seems to work pretty well, returning a rev=canonical url wherever possible.&lt;/p&gt;




&lt;p&gt;I also contributed a basic bit of code to &lt;a href=&quot;http://akrabat.com&quot;&gt;Rob Allen's&lt;/a&gt; &lt;a href=&quot;http://akrabat.com/shorter-links&quot;&gt;Shorter Links&lt;/a&gt; plugin for wordpress, allowing users to specifying a base url, davedevelopment.co.uk isn't all that good for short URLs. Just need to upgrade the plugin and decide on a short domain for my blog now.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: registerd &lt;a href=&quot;http://daved.in&quot;&gt;daved.in&lt;/a&gt;, works a treat&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Url Shortener in CodeIgniter</title>
      <link>http://davedevelopment.co.uk/2009/04/10/url-shortener-in-codeigniter.html</link>
      <pubDate>Fri, 10 Apr 2009 00:38:52 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/04/10/url-shortener-in-codeigniter</guid>
      <description>&lt;p&gt;After seeing a &lt;a href=&quot;http://news.ycombinator.com/item?id=550939&quot;&gt;response&lt;/a&gt; to a thread on &lt;a href=&quot;http://news.ycombinator.com&quot;&gt;Hacker News&lt;/a&gt;, I thought I'd have a crack at making a simple little URL shortener with &lt;a href=&quot;http://codeigniter.com/&quot;&gt;CodeIgniter&lt;/a&gt;. I've never used the framework before and it was a nice quick little app to implement and get a feel for things. It's not quite worthy of competing with &lt;a href=&quot;http://bit.ly&quot;&gt;Bit.ly&lt;/a&gt; or &lt;a href=&quot;http://tinyurl.com&quot;&gt;Tinyurl.com&lt;/a&gt;, there's no checking for spam urls etc, but if you want to take a look, the &lt;a href=&quot;http://github.com/davedevelopment/lnkd.in/tree/master&quot;&gt;source code is available&lt;/a&gt;, as is a live demo at &lt;a href=&quot;http://lnkd.in&quot; title=&quot;Shorten your urls&quot;&gt;lnkd.in&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ZFSnippets.com update</title>
      <link>http://davedevelopment.co.uk/2009/04/06/zfsnippetscom-update.html</link>
      <pubDate>Mon, 06 Apr 2009 21:17:13 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/04/06/zfsnippetscom-update</guid>
      <description>&lt;p&gt;It's been just &lt;a href=&quot;http://davedevelopment.co.uk/2009/03/04/zfsnippetscom-zend-framework-code-snippets/&quot;&gt;over a month&lt;/a&gt; since I launched &lt;a href=&quot;http://www.zfsnippets.com&quot; title=&quot;Zend Framework Snippets&quot;&gt;zfsnippets.com&lt;/a&gt; and I'm very pleased with the reception it got, which spurred me on to try and improve it. &lt;/p&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Since then, following suggestions on the &lt;a href=&quot;http://zfsnippets.uservoice.com/pages/general&quot;&gt;feedback forum&lt;/a&gt; I've implemented a few new features. What I've noticed is the ease at which these features where added, thanks to the quality of the Zend Framework.&lt;/p&gt;




&lt;h4&gt;Favourites&lt;/h4&gt;


&lt;p&gt;Along with adding icons for up votes, there's now a little star icon to add snippets to your favourites, easily accessible from your user page. A little sprinkling of &lt;a href=&quot;http://www.dojotoolkit.org/&quot;&gt;dojo&lt;/a&gt; and these are added via AJAX.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot2.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot2.png&quot; alt=&quot;screenshot2&quot; title=&quot;screenshot2&quot; width=&quot;129&quot; height=&quot;43&quot; class=&quot;alignnone size-full wp-image-370&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Revision History&lt;/h4&gt;


&lt;p&gt;Snippets can now be edited by the creator and a revision history is kept.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot3.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot3-300x167.png&quot; alt=&quot;screenshot3&quot; title=&quot;screenshot3&quot; width=&quot;300&quot; height=&quot;167&quot; class=&quot;alignnone size-medium wp-image-371&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using a simple implementation of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Longest_common_subsequence_problem&quot;&gt;Longest common subsequence problem&lt;/a&gt;, you can also view diffs of the revisions.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot4.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot4-300x102.png&quot; alt=&quot;screenshot4&quot; title=&quot;screenshot4&quot; width=&quot;300&quot; height=&quot;102&quot; class=&quot;alignnone size-medium wp-image-372&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Search&lt;/h4&gt;


&lt;p&gt;Lastly there's the &lt;a href=&quot;http://www.zfsnippets.com/snippets/search&quot;&gt;search engine&lt;/a&gt;, built on top of &lt;a href=&quot;http://framework.zend.com/manual/en/zend.search.lucene.html&quot;&gt;Zend_Search_Lucene&lt;/a&gt;. This took a little more work, but the results were worth it. I hadn't realised how powerful the Lucene query language was until now and I'm very impressed with the implementation.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot1.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/04/screenshot1-300x173.png&quot; alt=&quot;screenshot1&quot; title=&quot;screenshot1&quot; width=&quot;300&quot; height=&quot;173&quot; class=&quot;alignnone size-medium wp-image-373&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you would expect, traffic has slowed down considerably since the initial burst, but there's still a bit of steady traffic there and I hope people keep coming back to visit now and then. As for going forward, I think I'll add a field to allow contributors to &lt;a href=&quot;http://zfsnippets.uservoice.com/pages/general/suggestions/134574-add-zend-framework-version-number-snippet-was-tested-with-&quot;&gt;specify which zend framework version&lt;/a&gt; their snippet was tested or is compatible with, then look a little more at the scoring system. &lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Code Complete by Steve McConnell</title>
      <link>http://davedevelopment.co.uk/2009/03/25/code-complete-by-steve-mcconnell.html</link>
      <pubDate>Wed, 25 Mar 2009 11:00:06 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/03/25/code-complete-by-steve-mcconnell</guid>
      <description>&lt;p&gt;The only programming book I use without fail every working day ;)&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/03/dsc00185.jpg&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2009/03/dsc00185-300x225.jpg&quot; alt=&quot;My Monitor&quot; title=&quot;My Monitor&quot; width=&quot;300&quot; height=&quot;225&quot; class=&quot;alignnone size-medium wp-image-360&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seriously though, this book is great.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>ZFSnippets.com - Zend Framework Code Snippets</title>
      <link>http://davedevelopment.co.uk/2009/03/04/zfsnippetscom-zend-framework-code-snippets.html</link>
      <pubDate>Wed, 04 Mar 2009 13:25:04 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/03/04/zfsnippetscom-zend-framework-code-snippets</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.zfsnippets.com&quot;&gt;&lt;img style=&quot;float:left;margin-right:10px; margin-bottom:10px&quot; src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/03/screenshot1.png&quot; alt=&quot;ZFSnippets Logo&quot; title=&quot;screenshot1&quot; width=&quot;329&quot; height=&quot;72&quot; class=&quot;alignnone size-full wp-image-324&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not so long ago I was working on a little project using the &lt;a href=&quot;http://www.djangoproject.com/&quot;&gt;django framework&lt;/a&gt; and was looking for a simple &lt;a href=&quot;http://en.wikipedia.org/wiki/Nested_set_model&quot;&gt;nested set&lt;/a&gt; implementation, I found &lt;a href=&quot;http://www.djangosnippets.org/snippets/440/&quot;&gt;one&lt;/a&gt; that was good enough for my needs on &lt;a href=&quot; http://www.djangosnippets.org/&quot;&gt;djangosnippets.org&lt;/a&gt;. I thought this was pretty cool, and realised we didn't have a one stop shop for  &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; code snippets. &lt;a href=&quot;http://snippets.symfony-project.org/&quot;&gt;Symfony&lt;/a&gt; and &lt;a href=&quot;http://cakeforge.org/snippet/&quot;&gt;CakePHP&lt;/a&gt; also have dedicated sites for this. I'm aware of generic &lt;a href=&quot;http://snippets.dzone.com&quot;&gt;snippets sites&lt;/a&gt; and &lt;a href=&quot;http://gist.github.com/&quot;&gt;pastebin&lt;/a&gt; &lt;a href=&quot;http://pastie.org&quot;&gt;sites&lt;/a&gt;, but I thought it'd be &lt;a href=&quot;http://davedevelopment.co.uk/2008/09/29/phppositions-genuine-php-jobs-at-genuine-companies/&quot;&gt;another&lt;/a&gt; good learning opportunity to build my own with the Zend Framework, for the Zend Framework.&lt;/p&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I've ended up implementing a pretty simple site, &lt;a href=&quot;http://www.zfsnippets.com&quot; title=&quot;Zend Framework Code Snippets&quot;&gt;ZFSnippets&lt;/a&gt;. The current basic implementation makes use of:&lt;/p&gt;




&lt;ul style=&quot;float:left;margin-bottom:1.5em&quot;&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.auth.html&quot;&gt;Zend_Auth&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.config.html&quot;&gt;Zend_Config&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.controller.html&quot;&gt;Zend_Controller&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.db.html&quot;&gt;Zend_Db&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.feed.html&quot;&gt;Zend_Feed&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.form.html&quot;&gt;Zend_Form&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.layout.html&quot;&gt;Zend_Layout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;ul style=&quot;float:left&quot;&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.mail.html&quot;&gt;Zend_Mail&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.openid.html&quot;&gt;Zend_OpenId&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.paginator.html&quot;&gt;Zend_Paginator&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.registry.html&quot;&gt;Zend_Registry&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.session.html&quot;&gt;Zend_Session&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;&lt;a href=&quot;http://framework.zend.com/manual/en/zend.view.html&quot;&gt;Zend_View&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p style=&quot;clear:left;&quot;&gt;There are plenty of things I'd like to implement (and fix;)), but will have to see if I find anytime:&lt;/p&gt;




&lt;ul&gt;
     &lt;li&gt;A site search engine using &lt;a href=&quot;http://framework.zend.com/manual/en/zend.search.lucene.html&quot;&gt;Zend_Search_Lucene&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;More flexible posting, probably using wiki style &lt;a href=&quot;http://framework.zend.com/wiki/display/ZFPROP/Zend_Markup+-+Pieter+Kokx&quot;&gt;markup&lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;Version history for all snippets&lt;/li&gt;
     &lt;li&gt;Moving to a &lt;a href=&quot;http://stackoverflow.com&quot;&gt;stackoverflow.com&lt;/a&gt; style, trust model, allowing regular users to collaborate, edit and update snippets.&lt;/li&gt;
     &lt;li&gt;Forgot my password link&lt;/li&gt;
     &lt;li&gt;Contextual error handling and descriptions&lt;/li&gt;
     &lt;li&gt;Accurate scoring/ranking, based on &lt;a href=&quot;http://www.evanmiller.org/how-not-to-sort-by-average-rating.html&quot;&gt; complex calculations.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I did actually spend quite a bit of time looking at markup libraries, coupled with &lt;a href=&quot;http://htmlpurifier.org/&quot;&gt;HTMLPurifier&lt;/a&gt;, but it seemed like too much effort to start with, so I opted for a method of splitting the source code using hashes like pastie.&lt;/p&gt;




&lt;p&gt;I like the idea of having a go with Zend_Search_Lucene, probably adding particular snippets to a queue for indexing whenever somebody posts one or comments on one.&lt;/p&gt;




&lt;p&gt;Having built the site, I'm actually struggling to think of what might go on there. Helpers seem like an obvious one, but without building large, complex Zend Framework application, I don't have much need for custom code, the framework does the leg work for me. Nevermind, if you think it might be any use to you, head on over there and have a browse around, although it's a little low on content at the minute, or maybe &lt;a href=&quot;http://feeds2.feedburner.com/Zfsnippets&quot;&gt;subscribe to the feed&lt;/a&gt; and keep your eye out for anything interesting.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>How protected is protected?</title>
      <link>http://davedevelopment.co.uk/2009/02/25/how-protected-is-protected.html</link>
      <pubDate>Wed, 25 Feb 2009 22:18:21 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/02/25/how-protected-is-protected</guid>
      <description>&lt;p&gt;Before my much needed Holiday, &lt;a href=&quot;http://blog.chaddyonline.co.uk&quot;&gt;a colleague&lt;/a&gt; of mine asked for my input on a funny issue he was having. The root of the problem was that our production server is still running PHP 5.1.2, where as most of us run 5.2.x on our development and test machines. My problem was that what I was seeing didn't make sense. The following portion of code is a simple reproduction of the code my colleague was using, running fine on PHP 5.2.x, but causing a fatal error on the production server running 5.1.2, an attribute access violation.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
class BankAccount
{
    protected $balance;

    public function __construct($balance)
    {
        $this-&amp;gt;balance = $balance;
    }

    public function __toString()
    {
        return 'Balance: ' . $this-&amp;gt;balance;
    }

    public function debit($debit)
    {
        $this-&amp;gt;balance -= $credit;
    }

    public function credit($credit)
    {
        $this-&amp;gt;balance += $credit;
    }
}

class SavingsAccount extends BankAccount
{
    public function __construct(BankAccount $parent)
    {
        $this-&amp;gt;balance = $parent-&amp;gt;balance;
    }
}

$first = new BankAccount(1.00);
$second = new SavingsAccount($first);

echo $second, PHP_EOL; // Balance: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It turns out that &lt;a href=&quot;http://uk2.php.net/public&quot;&gt;PHP's visibility&lt;/a&gt; restrictions are on a class level, rather than an instance level, and the fatal error was actually due to a bug in 5.1.x.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The visibility of a property or method can be defined by prefixing the declaration with the keywords: public, protected or private. Public declared items can be accessed everywhere. Protected limits access to inherited and parent &lt;strong&gt;classes&lt;/strong&gt; (and to the &lt;strong&gt;class&lt;/strong&gt; that defines the item). Private limits visibility only to the class that defines the item. &lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;This bemused me, as it would appear to me there is no point having a protected operator at all. Suppose I am a lowly programmer given the BankAccount Class above as an API I can use but not change. I have a &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_Access_Object&quot;&gt;data access object&lt;/a&gt; that returns BankAccount objects too, which I also can't touch. For reasons unknown to me, but probably to try and create some &lt;a href=&quot;http://en.wikipedia.org/wiki/Encapsulation_(computer_science)&quot;&gt;encapsulation&lt;/a&gt; so they can log transactions via the credit and debit methods, the original developer decided that I shouldn't be able to directly access the balance attribute, but I want to.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

//$myAccount = $dao-&amp;gt;getAccount(123);
$myAccount = new BankAccount(1.00);
echo $myAccount, PHP_EOL; // Balance: 1

class WorkAround extends BankAccount
{
    public static function setBalance(BankAccount $acc, $balance)
    {
        $acc-&amp;gt;balance = $balance;
    }
}

WorkAround::setBalance($myAccount, 1000000.00);
echo $myAccount, PHP_EOL; // Balance: 1000000
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This just doesn't seem right to me. Don't get me wrong, I appreciate there needs to be some level of responsibility taken by developers to not do this kind of thing. My colleague writes a lot of &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_(programming_language)&quot;&gt;Java&lt;/a&gt;, in which this is also the expected behaviour with the protected visibility, hence why he set out on this path, so it seemed right to him. Because of this I embarked on a little research to determine how other languages implement visibility.&lt;/p&gt;

&lt;p&gt;A very quick and non-extensive bit of research led me to believe that Python doesn't have visibility as I know it, and C# has protected and internal, but neither work the way I'd like. Ruby has the closest to what I desire in the form of &lt;a href=&quot;http://www.rubyist.net/~slagell/ruby/instancevars.html&quot;&gt;instance variables&lt;/a&gt;, but I'm sure there's plenty I've missed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class BankAccount
    def initialize(bal)
        @balance = bal
    end

    def debit(debit)
        @balance -= debit
    end

    def credit(credit)
        @balance += credit
    end

    def to_s
        &quot;Balance: %d&quot; % @balance
    end
end

class SavingsAccount &amp;lt; BankAccount
    def setBalance(acc, bal)
        # This wont work - we cant access acc.balance
        # acc.balance = balance;
    end

    def bonusCredit(credit)
        # just to prove a sub class can access 
        # the instance variable
        @balance += credit + 1
    end
end

first = BankAccount.new(42);
second = SavingsAccount.new(1);

second.setBalance(first, 5000000);
second.bonusCredit(10);

print first  # Balance: 42
print second # Balance: 12 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It worries me sometimes when I come across things like this that I blatantly should know and understand properly. Cheers JC.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Competition: PHP Job Hunters Handbook up for grabs</title>
      <link>http://davedevelopment.co.uk/2009/01/05/competition-php-job-hunters-handbook-up-for-grabs.html</link>
      <pubDate>Mon, 05 Jan 2009 18:03:25 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2009/01/05/competition-php-job-hunters-handbook-up-for-grabs</guid>
      <description>&lt;p&gt;&lt;a style=&quot;float:left;margin:0px 10px 10px 0px;&quot; href=&quot;http://www.amazon.co.uk/gp/product/0973862165?ie=UTF8&amp;tag=davedvd-21&amp;linkCode=as2&amp;camp=1634&amp;creative=19450&amp;creativeASIN=0973862165&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2009/01/51jp8ktz0l_sl500_aa240_.jpg&quot; alt=&quot;PHP Job Hunter&amp;#039;s Handbook&quot; title=&quot;PHP Job Hunter&amp;#039;s Handbook&quot; width=&quot;240&quot; height=&quot;240&quot; class=&quot;alignnone size-full wp-image-283&quot; /&gt;&lt;/a&gt;I've got a couple of copies of &lt;a href=&quot;http://www.amazon.co.uk/gp/product/0973862165?ie=UTF8&amp;tag=davedvd-21&amp;linkCode=as2&amp;camp=1634&amp;creative=19450&amp;creativeASIN=0973862165&quot;&gt;Php|architect's PHP Job Hunter's Handbook&lt;/a&gt; to give away, the only catch is you have to sign up to &lt;a href=&quot;http://www.phppositions.co.uk&quot; title=&quot;PHP Jobs&quot;&gt;PHPPositions'&lt;/a&gt; feed via email. It's managed by &lt;a href=&quot;http://feedburner.com&quot;&gt;Feedburner&lt;/a&gt;, so it can be trusted and you wont get any spam, just super smashing great php jobs in the UK.&lt;/p&gt;

&lt;p&gt;&lt;form action=&quot;http://www.feedburner.com/fb/a/emailverify&quot; method=&quot;post&quot; target=&quot;popupwindow&quot; onsubmit=&quot;window.open('http://www.feedburner.com/fb/a/emailverifySubmit?feedId=2474733', 'popupwindow', 'scrollbars=yes,width=550,height=520');return true&quot;&gt;&lt;p&gt;Enter your email address:&lt;/p&gt;&lt;p&gt;&lt;input type=&quot;text&quot; style=&quot;width:140px&quot; name=&quot;email&quot;/&gt;&lt;/p&gt;&lt;input type=&quot;hidden&quot; value=&quot;http://feeds.feedburner.com/~e?ffid=2474733&quot; name=&quot;url&quot;/&gt;&lt;input type=&quot;hidden&quot; value=&quot;PHP Positions&quot; name=&quot;title&quot;/&gt;&lt;input type=&quot;hidden&quot; name=&quot;loc&quot; value=&quot;en_US&quot;/&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; /&gt;&lt;/form&gt;&lt;/p&gt;

&lt;p&gt;I'll pick two email addresses at random this time next week and get the books posted out.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Meeting Cost Clock</title>
      <link>http://davedevelopment.co.uk/2008/12/24/meeting-cost-clock.html</link>
      <pubDate>Wed, 24 Dec 2008 13:06:03 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/12/24/meeting-cost-clock</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/meetingclock/&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/12/screenshot8.png&quot; alt=&quot;Meeting Clock&quot; title=&quot;Meeting Clock&quot; width=&quot;446&quot; height=&quot;553&quot; class=&quot;alignnone size-full wp-image-273&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wrote a simple &lt;a href=&quot;http://davedevelopment.co.uk/meetingclock&quot; title=&quot;Meeting Cost Clock&quot;&gt;Meeting Cost Clock&lt;/a&gt; after having a little search on google for a simple one (I actually found &lt;a href=&quot;http://www.mcgurrin.com/clock.htm&quot;&gt;this one&lt;/a&gt; after writing mine). It's easy to use, you enter the number of participants, the average salary for those participants, then click start. It's a little rudimentary, the JavaScript is probably a little rough, but it'll serve me right.&lt;/p&gt;




&lt;p&gt;I've styled it using &lt;a href=&quot;http://code.google.com/p/iphone-universal/&quot;&gt;iPhone universal&lt;/a&gt;, a CSS framework for making iPhone stylee pages, so one of my colleagues can open it up on his iPhone in our next meeting.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Landing a PHP job Part 3: Curriculum Vitae</title>
      <link>http://davedevelopment.co.uk/2008/12/15/landing-a-php-job-part-3-curriculum-vitae.html</link>
      <pubDate>Mon, 15 Dec 2008 23:44:24 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/12/15/landing-a-php-job-part-3-curriculum-vitae</guid>
      <description>&lt;p&gt;In &lt;a href=&quot;http://davedevelopment.co.uk/2008/09/17/landing-a-php-job-part-2-soft-skills/&quot;&gt;part two&lt;/a&gt; of this series, I discussed the technical know how I think will help get you your next PHP job. This part will discuss writing your Curriculum Vitae(CV, resume, etc.). There are a lot of contrasting opinions on this subject, I'll make a few points, give you some further reading and you can adapt the opinions in to a top notch CV of your own. I'm no major expert and most of the recruitment I have been involved in has been for trainee developers, but these positions attract a high number of CVs, so I've seen a fair few. &lt;/p&gt;




&lt;h4&gt;Your CV does not get you a job&lt;/h4&gt;


&lt;p&gt;Your CV gets you an interview, your performance in the interview gets you a job. Your CV is a right of passage, this stage is used to &lt;em&gt;filter out&lt;/em&gt; the wrong candidates.&lt;/p&gt;




&lt;h4&gt;Your CV should evolve like you&lt;/h4&gt;


&lt;p&gt;You should be continually evolving and improving yourself, your CV should continually evolve with you. I can't see any reason why any two companies should see the same version of your CV. Every time you apply for a position, you CV should be tailored to suit the position. Cut out anything you think will not interest your prospective employer, embellish on what will interest them. You come across as a better candidate and you &lt;em&gt;don't waste their time&lt;/em&gt;. &lt;/p&gt;




&lt;h4&gt;Don't stuff your CV with keywords/acronyms&lt;/h4&gt;


&lt;blockquote&gt;
&lt;p&gt;Skills: PHP4/5, SOAP, XML, XSLT, JSON, AJAX, (X)HTML, CSS, RoR, MySQL, SEO, WAI, WCAG, MVC, XML-RPC....&lt;/p&gt;
&lt;/blockquote&gt;


&lt;p&gt;These kinds of lists are great for getting your CV past an agency recruiter, but the &lt;em&gt;actual&lt;/em&gt; employers would rather see a reasonable description of how you used 5 of those technologies. I try to briefly describe what I did and why I used those methods/skills/technologies.&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;.. Overcame performance issues due to large volumes of data by including caching, AJAX and moving some business logic to database triggers and stored procedures. (LAMP)&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Besides, if you're good, they'll hire you and expect you to quickly learn the skills, technologies and methods &lt;em&gt;they use&lt;/em&gt;.&lt;/p&gt;




&lt;h4&gt;Formatting and Proof Reading&lt;/h4&gt;


&lt;p&gt;I like CVs short, they take less time to read. One page is good, any more than two is bad. Keep it simple, spell check it, grammar check it, get people smarter than you to proof read it. Speaking of which, here's my &lt;a href='http://davedevelopment.co.uk/wp-content/uploads/2008/12/cv.pdf' title=&quot;Dave Marshalls CV&quot;&gt;current offering&lt;/a&gt;, although it still needs a lot of work. I intend to try switching to plain text, ala &lt;a href=&quot;http://steve-yegge.blogspot.com/2007/09/ten-tips-for-slightly-less-awful-resume.html&quot;&gt;Stevey&lt;/a&gt;, plus I recently got promoted so I've more work history to add. Comments appreciated.&lt;/p&gt;




&lt;h4&gt;Further Reading&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.manager-tools.com/2005/10/your-resume-stinks/&quot;&gt;Manager Tools - Resume podcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.manager-tools.com/sample-resume/&quot;&gt;Manager Tools - Sample Resume&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://steve-yegge.blogspot.com/2007/09/ten-tips-for-slightly-less-awful-resume.html&quot;&gt;Steve Yegge on CVs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.joelonsoftware.com/articles/ResumeRead.html&quot;&gt;Joel Spolsky - Getting your resume read&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.joelonsoftware.com/articles/SortingResumes.html&quot;&gt;Joel Spolsky - Sorting Resumes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.bcs.org/server.php?show=ConWebDoc.23143&quot;&gt;BCS CV Clinic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;More in this series&lt;/h4&gt;




&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/09/08/landing-a-php-job-part-1-technical-knowledge-and-skills/&quot; title=&quot;Technical skills for PHP Jobs&quot;&gt;Part 1: Technical Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/09/17/landing-a-php-job-part-2-soft-skills/&quot; title=&quot;Soft skills for PHP Jobs&quot;&gt;Part 2: Soft Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/12/15/landing-a-php-job-part-3-curriculum-vitae/&quot;&gt;Part 3: Curriculum Vitae&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    
    <item>
      <title>Changing hosts - Slicehost.com Review</title>
      <link>http://davedevelopment.co.uk/2008/11/11/changing-hosts-slicehostcom-review.html</link>
      <pubDate>Tue, 11 Nov 2008 15:20:02 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/11/11/changing-hosts-slicehostcom-review</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/11/logo.jpg&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/11/logo.jpg&quot; style=&quot;margin:0px 10px 10px 0px; float:left;&quot; alt=&quot;&quot; title=&quot;logo&quot; width=&quot;150&quot; height=&quot;78&quot; class=&quot;alignnone size-thumbnail wp-image-229&quot; /&gt;&lt;/a&gt;&lt;p&gt;I'm currently trying to &lt;a href=&quot;http://marketplace.sitepoint.com/auctions/49940&quot;&gt;sell&lt;/a&gt; &lt;a href=&quot;http://www.daveproxy.co.uk&quot;&gt;DaveProxy&lt;/a&gt; and as such will be switching to a more cost effective hosting solution. &lt;/p&gt;&lt;/p&gt;

&lt;p&gt;I've been using dedicated servers for quite some time now, initially with &lt;a href=&quot;http://www.layeredtech.com/&quot;&gt;LayeredTech&lt;/a&gt;, but after their &lt;a href=&quot;http://www.webhostingtalk.com/showthread.php?t=696677&quot;&gt;atrocious price increase&lt;/a&gt;, I promptly moved to &lt;a href=&quot;http://iweb.com/&quot;&gt;iWeb&lt;/a&gt;, who I would recommend.&lt;/p&gt;




&lt;p&gt;Moving away from the dedicated server arena I start looking at &lt;a href=&quot;http://en.wikipedia.org/wiki/Virtual_private_server&quot;&gt;Virtual Private Servers&lt;/a&gt;, which give all the benefits of running your own dedicated server, usually at a fraction of the price, along with a few added benefits. This lead me to Slicehost.com.&lt;/p&gt;




&lt;h4&gt;Slicehost&lt;/h4&gt;


&lt;p&gt;&lt;a href=&quot;http://www.slicehost.com&quot;&gt;Slicehost&lt;/a&gt; were a name I'd heard of, so I went to check them out. Their tagline, 'Built for Developers', just about sums it all up for me. With plans starting from just $20/month, I was instantly interested and their well designed website answered all the questions I needed. The features that did it for me the most:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slicehost.com/articles/2006/9/18/ajax-console-for-your-slice&quot;&gt;Ajax console access&lt;/a&gt; - The management portal has an Ajax terminal, just in case your SSH goes down&lt;/li&gt;
&lt;li&gt;No contracts, no setup fees. - Always a bonus&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slicehost.com/questions/#upgrade&quot;&gt;Upgrade, downgrade, add a slice or remove a slice anytime&lt;/a&gt;. - This is a thing of beauty. Because your VPS is essential a disk image, if you decide you need more RAM, disk space or bandwidth, you can simply upgrade via the management portal. Your VPS will be taken down and fired back up in a more powerful virtual machine.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slicehost.com/questions/#backups&quot;&gt;Backups&lt;/a&gt; - Again, because your VPS is stored as a disk image, starting from $5/month, you can have upto 3 snapshots (1 daily, 1 weekly and 1 variable) of your VPS available to restore at any time.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Another bonus, they were recently &lt;a href=&quot;http://www.slicehost.com/articles/2008/10/22/big-news-today&quot;&gt;acquired&lt;/a&gt; by &lt;a href=&quot;http://www.rackspace.com/&quot;&gt;Rackspace&lt;/a&gt;, so you can rest assured they are fairly stable and not going anywhere.&lt;/p&gt;




&lt;h4&gt;My Slice&lt;/h4&gt;




&lt;p&gt;Ordering a slice was nice and easy and what really impressed me was the time it took for my slice to be ready to use. I'm used to a 48 hour wait on new dedicated servers, but as you can imagine, creating a new virtual machine takes a matter of minutes. After confirming my details I was taken to the management portal, which showed my slice as 60% built. Two refreshes later and it was complete, I checked my email and my user credentials were waiting for me.&lt;/p&gt;




&lt;p&gt;The management portal is also excellent, it's really nice and basic in terms of looks, no fancy gradients.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/11/slicehost.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/11/slicehost.png&quot; alt=&quot;&quot; title=&quot;slicehost&quot; width=&quot;300&quot; height=&quot;155&quot; class=&quot;alignnone size-medium wp-image-237&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog is the only site I have moved over so far, it was nice and simple as the slice is running &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu&lt;/a&gt; like my dedicated server.&lt;/p&gt;




&lt;p&gt;Only time will tell how reliable they are, but I'm extremely impressed so far.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Going to PHPNW08</title>
      <link>http://davedevelopment.co.uk/2008/11/03/going-to-phpnw08.html</link>
      <pubDate>Mon, 03 Nov 2008 15:58:12 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/11/03/going-to-phpnw08</guid>
      <description>&lt;p&gt;In a few weeks a few colleagues and myself will be attending &lt;a href=&quot;http://conference.phpnw.org.uk/phpnw08/&quot;&gt;phpnw08&lt;/a&gt;, a PHP conference arranged by the &lt;a href=&quot;http://phpnw.org.uk/&quot;&gt;PHPNW&lt;/a&gt; community. &lt;/p&gt;




&lt;blockquote&gt;&lt;p&gt;phpnw08 is a 1 day conference, to be held on Saturday 22nd November 2008, for developers, designers, managers or anyone else with an interest in the PHP programming language.&lt;/p&gt;
&lt;p&gt;The conference will have a range of well known as well as more local speakers and aims to highlight current best practice and emerging topics within the sphere of PHP and web development.&lt;/p&gt;&lt;/blockquote&gt;




&lt;p&gt;This will be the first conference I've attended and I'm lucky enough to have my ticket paid for by &lt;a href=&quot;http://www.cspencerltd.co.uk&quot;&gt;Spencers&lt;/a&gt;. I'm particularly looking forward to the keynote with &lt;a href=&quot;http://www.derickrethans.nl/&quot;&gt;Derick Rethans&lt;/a&gt;, The Power of Refactoring with &lt;a href=&quot;http://www.leftontheweb.com/&quot;&gt;Stefan Koopmanschap&lt;/a&gt; and the final panel with &lt;a href=&quot;http://devzone.zend.com/member/83-Steph-Fox-staff&quot;&gt;Steph Fox&lt;/a&gt;, &lt;a href=&quot;http://www.jansch.nl/&quot;&gt;Ivo Jansch&lt;/a&gt;, &lt;a href=&quot;http://www.macvicar.net/&quot;&gt;Scott Macvicar&lt;/a&gt; and &lt;a href=&quot;http://felix.phpbelgium.be/blog/&quot;&gt;Felix De Vliegher&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Anybody else who's going, that's my picture over on the right, if you see me, please introduce yourself! Anybody who's in the UK and not going, &lt;a href=&quot;http://conference.phpnw.org.uk/phpnw08/register&quot;&gt;register now&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Programming in C and stackoverflow.com</title>
      <link>http://davedevelopment.co.uk/2008/10/30/programming-in-c-and-stackoverflowcom.html</link>
      <pubDate>Thu, 30 Oct 2008 14:16:55 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/10/30/programming-in-c-and-stackoverflowcom</guid>
      <description>&lt;p&gt;I recently had to stroll from the PHP path, at work we required a very simple program that had to be run as &lt;a href=&quot;http://en.wikipedia.org/wiki/Setuid&quot;&gt;setuid&lt;/a&gt;. Now, as far as I can tell, both &lt;a href=&quot;http://www.debian.org/&quot;&gt;debian&lt;/a&gt; and &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;ubuntu&lt;/a&gt; do not allow scripts to setuid, only binaries. This led to me flexing my C skills, which haven't been touched since I was following &lt;a href=&quot;http://nehe.gamedev.net/&quot;&gt;NeHe's OpenGL tutorials&lt;/a&gt; for my graphics module back at uni. I couldn't actually remember how to do anything, so I had a quick read through a few chapters from my &lt;a href=&quot;http://www.cs.cf.ac.uk/Dave/C/CE.html&quot;&gt;namesakes guide&lt;/a&gt; (I'm gunning for his place in the google rankings for my name) and set about on my task.&lt;/p&gt;

&lt;p&gt;I managed to do everything I needed using the guide, except for one simple task. In PHP, we have the &lt;a href=&quot;http://uk.php.net/file_exists&quot;&gt;file_exists&lt;/a&gt; function, which works a treat. There's no such function in C, which is understandable as it is a much higher level language, so I had to hit the search engines to find an example. The result at the top of the list was actually a forum post asking the exact &lt;a href=&quot;http://www.gamedev.net/community/forums/topic.asp?topic_id=266856&quot;&gt;same question&lt;/a&gt; I was asking google. Now being the naive person I am, I took the first correct response as gospel and implemented it, it worked and I was happy. Now, a few hours later my program was finished and I as read through the code again, the file_exists function I'd created was nagging at me. The function basically ran fopen on the file, returning true upon success, which I assumed was slightly overkill.&lt;/p&gt;

&lt;p&gt;I've been keeping my eye on &lt;a href=&quot;http://www.stackoverflow.com&quot;&gt;stackoverflow&lt;/a&gt; since the first announcement, including listening to all the podcasts and participating in the private beta. Joel Spolsky and &lt;a href=&quot;http://www.codinghorror.com/&quot;&gt;Jeff Atwood&lt;/a&gt; have done extremely well in building a giant community of programmers and I figured I'd get the answer I needed there. I asked my &lt;a href=&quot;http://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform&quot;&gt;question&lt;/a&gt; and in moments I had several answers. Turned out that there were two methods better than my own and I had to make a decision and award the 'correct' answer to one of them. Even so, the other answer was well voted up, so what I considered the second best response, was directly under my accepted answer. A week later and I thought I'd check the google rankings, to see how close to the top my question would be. It could be closer, but a search for &lt;a href=&quot;http://www.google.co.uk/search?q=file+exists+in+C&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=com.ubuntu:en-GB:unofficial&amp;client=firefox-a&quot;&gt;file exists in C&lt;/a&gt; shows my question just on the first page and I'm sure with time, will make it to the top. In doing so, I had another look at the original forum thread that I got the fopen code from and low and behold, the last three posts detailed the same two answers that I got from stackoverflow. The difference? When people go to my stackoverflow.com question, the best solution is the first thing they see after the question.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Zend Framework and the Twitter API</title>
      <link>http://davedevelopment.co.uk/2008/10/13/zend-framework-and-the-twitter-api.html</link>
      <pubDate>Mon, 13 Oct 2008 14:16:58 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/10/13/zend-framework-and-the-twitter-api</guid>
      <description>&lt;p&gt;I wanted my new &lt;a href=&quot;http://www.phppositions.co.uk&quot; title=&quot;UK PHP Jobs&quot;&gt;job website&lt;/a&gt; to post a tweet to &lt;a href=&quot;http://twitter.com/&quot;&gt;twitter&lt;/a&gt; every time we approved a posting. &lt;/p&gt;




&lt;p&gt;&lt;a href=&quot;http://framework.zend.com/wiki/display/ZFPROP/Zend_Service_Twitter&quot;&gt;Zend_Service_Twitter&lt;/a&gt; looks like it will be fairly comprehensive, but it's not in the core yet and is probably a little overkill for my simple use case. &lt;/p&gt;




&lt;p&gt;I then had a look at &lt;a href=&quot;http://framework.zend.com/manual/en/zend.rest.client.html&quot;&gt;Zend_Rest_Client&lt;/a&gt;, which seemed to confuse me. I couldn't actually get it to add the parameters I wanted to the call, I guess it's better for interacting with &lt;a href=&quot;http://framework.zend.com/manual/en/zend.rest.server.html&quot;&gt;Zend_Rest_Server&lt;/a&gt; or fully &lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;restful&lt;/a&gt; APIs.
&lt;/p&gt;




&lt;p&gt;To be fair, the manual actually states:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;[Warning]  Strictness of Zend_Rest_Client&lt;/p&gt;

&lt;p&gt;Any REST service that is strict about the arguments it receives will likely fail using Zend_Rest_Client, because of the behavior described above. This is not a common practice and should not cause problems.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So here's some simple code using &lt;a href=&quot;http://framework.zend.com/manual/en/zend.http.html&quot;&gt;Zend_Http_Client&lt;/a&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt; ?php
require_once 'Zend/Http/Client.php';

$http = new Zend_Http_Client('http://twitter.com/statuses/update.xml', array(
    'maxredirects' =&amp;gt; 0,
    'timeout'      =&amp;gt; 10,
));

$http-&amp;gt;setAuth(
    'twitter_username',
    'twitter_password',
     Zend_Http_Client::AUTH_BASIC
);

$http-&amp;gt;setMethod(Zend_Http_Client::POST);
$http-&amp;gt;setParameterPost('status', 'Your status message');
$http-&amp;gt;request();

?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>PHPPositions - Genuine PHP jobs at Genuine Companies</title>
      <link>http://davedevelopment.co.uk/2008/09/29/phppositions-genuine-php-jobs-at-genuine-companies.html</link>
      <pubDate>Mon, 29 Sep 2008 21:51:03 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/09/29/phppositions-genuine-php-jobs-at-genuine-companies</guid>
      <description>&lt;p&gt;&lt;a style=&quot;float:left;margin:0px 10px 10px 0px;&quot; href=&quot;http://www.phppositions.co.uk&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/logo_94x70.png&quot; alt=&quot;&quot; title=&quot;PHPPositions&quot; width=&quot;94&quot; height=&quot;70&quot; class=&quot;alignleft size-full wp-image-193&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.phppositions.co.uk&quot; title=&quot;Find PHP jobs&quot;&gt;PHPPositions UK&lt;/a&gt; is a simple job board, listing genuine PHP jobs, for genuine companies. No agencies.&lt;/p&gt;




&lt;p&gt;I needed a little project to help get to grips with the &lt;a href=&quot;http://framework.zend.com&quot;&gt;Zend Framework&lt;/a&gt;, so I created a little job board specifically targetted at PHP jobs in the UK. It's not finished yet, but it's good enough to put up on the web.&lt;/p&gt;




&lt;p&gt;Check it out, if you're in the UK and on the lookout for positions, subscribe to the &lt;a href=&quot;http://feeds.feedburner.com/PhpPositions&quot;&gt;feed&lt;/a&gt;. Eventually I'd like to monetise the site, but that depends on it generating a large enough audience, so until that point I'll be adding jobs manually, thus keeping up a fairly  high standard of jobs on there.&lt;/p&gt;




&lt;br style=&quot;clear:both&quot; /&gt;

</description>
    </item>
    
    <item>
      <title>Quick SVN stats one liner</title>
      <link>http://davedevelopment.co.uk/2008/09/26/quick-svn-stats-one-liner.html</link>
      <pubDate>Fri, 26 Sep 2008 11:00:29 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/09/26/quick-svn-stats-one-liner</guid>
      <description>&lt;p&gt;I needed a quick list of contributors to our repository, this one liner is nice and easy.&lt;/p&gt;

&lt;pre name=&quot;code&quot;&gt;
svn log -q | awk '/^r/ {print $3}' | sort | uniq -c
&lt;/pre&gt;

</description>
    </item>
    
    <item>
      <title>Landing a PHP job Part 2: Soft Skills </title>
      <link>http://davedevelopment.co.uk/2008/09/16/landing-a-php-job-part-2-soft-skills.html</link>
      <pubDate>Tue, 16 Sep 2008 23:23:20 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/09/16/landing-a-php-job-part-2-soft-skills</guid>
      <description>&lt;p&gt;In &lt;a href=&quot;http://davedevelopment.co.uk/2008/09/08/landing-a-php-job-part-1-technical-knowledge-and-skills/&quot; title=&quot;Skills for PHP Jobs&quot;&gt;part one&lt;/a&gt; of this series, I discussed the technical know how I think will help get you your next PHP job. This part points out some of the soft skills that are required for software development, discussing reasoning and how to go about acquiring those skills.&lt;/p&gt;




&lt;h3&gt;Writing&lt;/h3&gt;


&lt;p&gt;Like it or not, PHP developers are going to have to write documents of some kind as part of their job. You need to produce clear and concise documentation, including but not limited to requirements specifications, design specifications, technical documentation, end user documentation and possibly evening marketing documents and copy depending on the size of your company. Three quarters of this post is about communicating in different forms, getting your ideas across on paper is the first step to being better than the average programmer. Joel Spolsky actually recommends programmers take a &lt;a href=&quot;http://en.wikipedia.org/wiki/Creative_writing&quot;&gt;creative writing&lt;/a&gt; course.&lt;/p&gt;




&lt;h3&gt;Listening&lt;/h3&gt;


&lt;p&gt;The guys at &lt;a href=&quot;http://www.manager-tools.com/&quot;&gt;Manager Tools&lt;/a&gt; had an episode on &lt;a href=&quot;http://www.manager-tools.com/2008/06/how-to-coach-directs-on-interpersonal-skills-part-2/&quot;&gt;teaching people interpersonal skills&lt;/a&gt; a while back and they made the point that being a good speaker is great, as long as you've got something great to say. If you can't listen to other people, you'll never have anything good to say. That cast is worth checking out, the points made are easily applied to yourself rather than other people.&lt;/p&gt;




&lt;p&gt;Another nice article, this one concentrates on the &lt;a href=&quot;http://sklatch.net/thoughtlets/listen.html&quot;&gt;barriers&lt;/a&gt; we all face while trying to listen to people, read it and be concious of them. The first time you put them into practice might be an interview, which you can't afford to mess up.&lt;/p&gt;




&lt;p&gt;You're going to have to listen to lots of people, people you report to, people who report to you and clients. The better you are at listening, the better you'll be at your job. &lt;/p&gt;




&lt;h3&gt;Speaking&lt;/h3&gt;


&lt;p&gt;When it comes to speaking, I find the most important rule is to know &lt;strong&gt;what&lt;/strong&gt; you want to say. Sometimes we're forced into situations where we have to act and speak on instinct, but these situations are the minority. Most of our speaking comes in the form of meetings and presentations, both of which are usually arranged in advanced. If they are arranged in advance, you should have time to plan what you want to say in advance and also what you want to get out of it.  Even if things don't go quite according to plan, the fact that you had a plan should have at the very least raised your confidence. Confidence can be quite a key factor when speaking, many things affect our confidence. For example, in my eyes an easy win is to look smart. If you look smart, or at least feel like you look smart, your confidence will be higher and the way you communicate will be better.
&lt;/p&gt;




&lt;h3&gt;Time Management&lt;/h3&gt;


&lt;p&gt;&lt;a style=&quot;float:left;margin:0px 10px 10px 0px;&quot; href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FGetting-Things-Done-Stress-Free-Productivity%2Fdp%2F0142000280%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1221606409%26sr%3D8-1&amp;tag=davedvd-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/gtd.jpg&quot; alt=&quot;&quot; title=&quot;gtd&quot; width=&quot;141&quot; height=&quot;204&quot; class=&quot;alignnone size-full wp-image-179&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Productivity is key, whatever you do. I'm a big fan of Getting Things Done and I use &lt;a href=&quot;http://www.rememberthemilk.com/&quot;&gt;Remember the Milk&lt;/a&gt; to manage my tasks. &lt;a href=&quot;http://www.lifehacker.com&quot;&gt;LifeHacker&lt;/a&gt; has a nice article on &lt;a href=&quot;http://www.lifehack.org/articles/productivity/gtd-with-rtm-getting-things-done-with-remember-the-milk.html&quot;&gt;GTD with RTM&lt;/a&gt;. &lt;/p&gt;


&lt;br style=&quot;clear:left;&quot; /&gt;


&lt;p&gt;&lt;a style=&quot;float:left;margin:0px 10px 10px 0px;&quot; href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FSoftware-Estimation-Demystifying-Practices-Microsoft%2Fdp%2F0735605351%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1221606774%26sr%3D8-1&amp;tag=davedvd-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/estimate.jpg&quot; alt=&quot;&quot; title=&quot;estimate&quot; width=&quot;141&quot; height=&quot;163&quot; class=&quot;alignnone size-full wp-image-180&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While not strictly a soft skill, without being able to give reasonable estimates for development work, you wont be able to manage your time effectively. Software estimation is exceptionally difficult, this book comes highly recommended, but if you want some lighter reading, I recommend Joel Spolskys &lt;a href=&quot;http://www.joelonsoftware.com/articles/fog0000000245.html&quot;&gt;Painless Software Schedules&lt;/a&gt;. That post actual says it is obsolete, but I don't think it's true, the &lt;a href=&quot;http://www.joelonsoftware.com/items/2007/10/26.html&quot;&gt;Evidence Based Scheduling&lt;/a&gt; article takes things to another level, but the base techniques are still the same.&lt;/p&gt;


&lt;br style=&quot;clear:left;&quot; /&gt;




&lt;h3&gt;Influence&lt;/h3&gt;


&lt;p&gt;&lt;a style=&quot;float:left;margin:0px 10px 10px 0px;&quot; href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FInfluence-Psychology-Persuasion-Business-Essentials%2Fdp%2F006124189X&amp;tag=davedvd-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325&quot;&gt;&lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/influence.jpg&quot; alt=&quot;&quot; title=&quot;influence&quot; width=&quot;141&quot; height=&quot;212&quot; class=&quot;alignnone size-full wp-image-177&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm part way through this book and I'm yet to put it to much use, but it's a bloody good read. Being able to influence people comes in handy in all walks of life, selling software, recommending the latest technology to your boss or peers or convincing your boss you really need to go to &lt;a href=&quot;http://www.zendcon.com/&quot;&gt;ZendCon&lt;/a&gt;.&lt;/p&gt;


&lt;br style=&quot;clear:left;&quot; /&gt;




&lt;p&gt;That's it for now, I'll be back with part 3 soon, which will be on writing your CV/Resume.&lt;/p&gt;




&lt;h4&gt;More in this series&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/09/08/landing-a-php-job-part-1-technical-knowledge-and-skills/&quot; title=&quot;Technical skills for PHP Jobs&quot;&gt;Part 1: Technical Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/09/17/landing-a-php-job-part-2-soft-skills/&quot; title=&quot;Soft skills for PHP Jobs&quot;&gt;Part 2: Soft Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/12/15/landing-a-php-job-part-3-curriculum-vitae/&quot;&gt;Part 3: Curriculum Vitae&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



</description>
    </item>
    
    <item>
      <title>Landing A Php Job Part 1 Technical Knowledge And Skills</title>
      <link>http://davedevelopment.co.uk/2008/09/08/landing-a-php-job-part-1-technical-knowledge-and-skills.html</link>
      <pubDate>Mon, 08 Sep 2008 00:00:00 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/09/08/landing-a-php-job-part-1-technical-knowledge-and-skills</guid>
      <description>&lt;hr /&gt;

&lt;p&gt;wordpress_id: 101
layout: post
title: Landing a PHP job Part 1: Technical Knowledge and Skills
date: 2008-09-08 22:28:28 +01:00
wordpress_url: http://davedevelopment.co.uk/?p=101&lt;/p&gt;

&lt;p&gt;--- &lt;a style=&quot;float:left;margin:0px 10px 10px 0px;&quot;
href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fphp-architects-PHP-Hunters-Handbook%2Fdp%2F0973862165&amp;tag=davedvd-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325&quot;&gt;&lt;img
src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/51jp8ktz0l_sl500_aa240_.jpg&quot;
alt=&quot;PHP Job Hunters Handbook&quot; title=&quot;PHP Job Hunters Handbook&quot; width=&quot;150&quot;
height=&quot;185&quot; class=&quot;alignnone size-full wp-image-128&quot; /&gt;&lt;/a&gt;  After reading
this &lt;a
href=&quot;http://groups.google.com/group/phpnw/browse_thread/thread/f42a1b18d39c8ce&quot;&gt;thread&lt;/a&gt;,
I thought I'd spend some time writing about what I feel are some measures you
can take to landing a job in PHP. This first part is going to concentrate on the
kind of technical matters I think any PHP developer should at least have
knowledge of, if not some kind of experience. A lot of the subjects discussed
aren't specific to PHP, but the focus will be on PHP. It'll be far from
exhaustive (please feel free to flame, but constructive comments would be nicer)
and there'll probably be quite a few references to &lt;a
href=&quot;http://www.joelonsoftware.com&quot;&gt;Joel on Software&lt;/a&gt; articles, mainly
because I've read a lot of them and I can't be bothered to research the topics
further! There'll be plenty of links to follow, plus the odd &lt;a
href=&quot;http://en.wikipedia.org/wiki/Hard_copy&quot;&gt;dead tree format&lt;/a&gt;
recommendation.   &lt;br style=&quot;clear:left;&quot;/&gt;  &lt;h3&gt;Programming&lt;/h3&gt;  &lt;a
style=&quot;float:left;margin:0px 10px 10px 0px&quot;
href=&quot;http://www.amazon.com/exec/obidos/ASIN/0735619670/davedvd-20&quot;&gt;&lt;img
src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/cc2e.jpg&quot; alt=&quot;Code
Complete 2&quot; title=&quot;Code Complete 2&quot; width=&quot;150&quot; height=&quot;188&quot; class=&quot;alignnone
size-full wp-image-129&quot; /&gt;&lt;/a&gt;  &lt;p&gt;This should be a no brainer. Lots of
experience of &lt;em&gt;programming&lt;/em&gt; in PHP, is not strictly necessary, a good
programmer, particularly with experience of scripting languages or programming
for the web should be able to pick up PHP in no time.&lt;/p&gt;  &lt;blockquote
cite=&quot;http://www.joelonsoftware.com/articles/SortingResumes.html&quot;&gt;&lt;p&gt;For someone
who is basically a good software developer, learning another programming
language is just not going to be a big deal. In two weeks they'll be pretty
productive. In two years, you may need them to do something completely different
in a programming language which hasn't even been invented.&lt;/p&gt; &lt;p&gt;&lt;a
href=&quot;http://www.joelonsoftware.com/articles/SortingResumes.html&quot;&gt;- Sorting
Resumes&lt;/a&gt; by Joel Spolsky&lt;/p&gt;&lt;/blockquote&gt;   &lt;p&gt;Most PHP applications are
used in conjunction with an SQL database, predominantly &lt;a
href=&quot;http://www.mysql.com&quot;&gt;MySQL&lt;/a&gt;, so you're going to need some of this
under your belt.&lt;/p&gt;  &lt;p&gt;Some knowledge of PHP is essential. Be aware of the
benefits, the caveats and if you're interested, a little of &lt;a
href=&quot;http://www.php.net/history&quot;&gt;PHPs history&lt;/a&gt;, some people &lt;a
href=&quot;http://hasin.wordpress.com/2008/05/12/i-dont-give-you-a-damn-if/&quot;&gt;really
care&lt;/a&gt; about it. I think it definitely shows you are passionate about what you
do or want to do. Maybe look to PHP's future, research whats coming up in &lt;a
href=&quot;http://www.sitepoint.com/article/whats-new-php-5-3/&quot;&gt;PHP 5.3&lt;/a&gt;, or
whatever the next version is at the current time.&lt;/p&gt; &lt;br style=&quot;clear:left;&quot;
/&gt;  &lt;h3&gt;Software Engineering&lt;/h3&gt;  &lt;p&gt;Most PHP roles go beyond just
programming, so a good sense of what's involved in a full project life cycle
should help you get that PHP job over the next guy. There are lots of processes
and models available, but you don't need to be familiar with them all. Get a
good idea of the 7 stages of the traditional &lt;a
href=&quot;http://en.wikipedia.org/wiki/Waterfall_model&quot;&gt;Waterfall Model&lt;/a&gt; and you
should be able to apply the principles to most methods. They are: &lt;ol&gt;
&lt;li&gt;Requirements Specification&lt;/li&gt; &lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Implementation&lt;/li&gt; &lt;li&gt;Integration&lt;/li&gt; &lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Installation&lt;/li&gt; &lt;li&gt;Maintenance&lt;/li&gt; &lt;/ol&gt;  &lt;/p&gt;&lt;p&gt;I like &lt;a
href=&quot;http://en.wikipedia.org/wiki/Unified_Modeling_Language&quot;&gt;UML&lt;/a&gt; for design
and documentation, so worth knowing about even if you haven't practiced
it.&lt;/p&gt;  &lt;h3&gt;Libraries and Frameworks&lt;/h3&gt; &lt;a style=&quot;float:left;margin:0px
10px 10px 0px;&quot;
href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Farchitects-Guide-Programming-Zend-Framework%2Fdp%2F0973862157%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1220909271%26sr%3D8-1&amp;tag=davedvd-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325&quot;&gt;&lt;img
src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/51apwbg78zl_sl500_aa240_.jpg&quot;
alt=&quot;&quot; title=&quot;Guide to Programming with Zend Framework&quot; width=&quot;150&quot; height=&quot;186&quot;
class=&quot;alignnone size-full wp-image-145&quot; /&gt;&lt;/a&gt; &lt;p&gt;If you are familiar with
Object Oriented methodologies, arm yourself with the knowledge of &lt;a
href=&quot;http://uk.php.net/zend-engine-2.php&quot;&gt;PHP5's OO&lt;/a&gt; capabilities. Once
you've got that, get a handle of the vast array of &lt;a
href=&quot;http://www.phpframeworks.com/&quot;&gt;PHP frameworks&lt;/a&gt; that are available. You
don't have to know them inside and out, just be aware of them and the benefits
they give you. &lt;a href=&quot;http://pear.php.net&quot;&gt;PEAR&lt;/a&gt; is a huge library of PHP
code, check it out&lt;/p&gt;  &lt;br style=&quot;clear:left;&quot; /&gt;  &lt;h3&gt;Development
Tools&lt;/h3&gt; &lt;p&gt;There are plenty of &lt;a
href=&quot;http://davedevelopment.co.uk/2008/03/20/10-tools-for-modern-php-development/&quot;&gt;tools&lt;/a&gt;
available to aid and improve the development process, be familiar with as many
as you can handle. I would insist on becoming familiar with, downloading and
experimenting with &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;subversion&lt;/a&gt;, or &lt;a
href=&quot;http://git.or.cz/&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;http://bazaar-vcs.org/&quot;&gt;other&lt;/a&gt;
version control system.   &lt;/p&gt;&lt;p&gt;Joel Spolsky has what he refers to &lt;a
href=&quot;http://www.joelonsoftware.com/articles/fog0000000043.html&quot;&gt;The Joel
Test&lt;/a&gt;. Later in this series, we'll discuss interviews, and I will recommend
asking at least one of these questions at an interview, so you need to
understand what they all mean and why they might benefit a software development
team.&lt;/p&gt;  &lt;h3&gt;Security&lt;/h3&gt; &lt;a style=&quot;float:left;margin:0px 10px 10px
0px;&quot;
href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FEssential-PHP-Security-Chris-Shiflett%2Fdp%2F059600656X%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1220471983%26sr%3D1-1&amp;tag=davedvd-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325&quot;&gt;
&lt;img
src=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/09/essential-php-security-198.gif&quot;
alt=&quot;Essential PHP Security&quot; title=&quot;Essential PHP Security&quot; width=&quot;150&quot;
height=&quot;196&quot; class=&quot;alignnone size-full wp-image-130&quot; /&gt;&lt;/a&gt; &lt;p&gt;Security is
often a big cause for concern in the PHP world, mainly because it's not been
handled correctly before. PHP is not insecure in itself, most vulnerabilities
attributed to PHP are actually simply in softwares written in PHP. &lt;/p&gt;&lt;/p&gt;

&lt;p&gt;Be aware of security issues in your code such as &lt;a
href=&quot;http://en.wikipedia.org/wiki/SQL_injection&quot;&gt;SQL Injection&lt;/a&gt;, &lt;a
href=&quot;http://en.wikipedia.org/wiki/Cross-site_scripting&quot;&gt;XSS&lt;/a&gt; and &lt;a
href=&quot;http://en.wikipedia.org/wiki/Cross-site_request_forgery&quot;&gt;CSRF&lt;/a&gt;. Also be
aware of configuration directives that can affect the security of your PHP
powered web servers.&lt;/p&gt;


&lt;p&gt; &lt;br style=&quot;clear:left;&quot; /&gt;  &lt;h3&gt;Web
Services&lt;/h3&gt; &lt;p&gt;Understand what a &lt;a
href=&quot;http://en.wikipedia.org/wiki/Web_service&quot;&gt;web service&lt;/a&gt; is and some of
the related technologies. PHP is ideal as a &lt;a
href=&quot;http://en.wikipedia.org/wiki/Glue_language&quot;&gt;glue language&lt;/a&gt;, combining
web services to consume single web services or  create &lt;a
href=&quot;http://en.wikipedia.org/wiki/Mashup_(web_application_hybrid)&quot;&gt;mash ups&lt;/a&gt;
of several web services, but can also be used for providing web services.&lt;/p&gt;

&lt;h3&gt;System Administration&lt;/h3&gt;


&lt;p&gt; &lt;/p&gt;&lt;p&gt;In my opinion, developers should be
capable of administering the full stack they develop for, usually in this case,
the &lt;a href=&quot;http://en.wikipedia.org/wiki/LAMP_(software_bundle)&quot;&gt;LAMP&lt;/a&gt;
stack. There can't be many potential PHP developers out there who don't have a
spare computer or hard disk lying around that they can't install &lt;a
href=&quot;http://www.debian.org/&quot;&gt;Debian&lt;/a&gt; on and follow a simple &lt;a
href=&quot;http://www.debian-administration.org/articles/357&quot;&gt;LAMP installation
tutorial&lt;/a&gt;. If you've not got a spare hard disk, download &lt;a
href=&quot;http://www.vmware.com/products/player/&quot;&gt;VmWare Player&lt;/a&gt; and a &lt;a
href=&quot;http://www.vmware.com/appliances/directory/838&quot;&gt;debian appliance&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;I think thats all I can think of for now, I'm sure there's plenty I've
missed. If there's any technical leads, managers or recruiters reading, please
pipe up with what you expect from your applicants. The next part in the series
will focus on the soft skills required for banking that PHP job.&lt;/p&gt;&lt;/p&gt;

&lt;h4&gt;More in this series&lt;/h4&gt;


&lt;p&gt;  &lt;ul&gt; &lt;li&gt;&lt;a
href=&quot;http://davedevelopment.co.uk/2008/09/08/landing-a-php-job-part-1-technical-knowledge-and-skills/&quot;
title=&quot;Technical skills for PHP Jobs&quot;&gt;Part 1: Technical Skills&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a
href=&quot;http://davedevelopment.co.uk/2008/09/17/landing-a-php-job-part-2-soft-skills/&quot;
title=&quot;Soft skills for PHP Jobs&quot;&gt;Part 2: Soft Skills&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a
href=&quot;http://davedevelopment.co.uk/2008/12/15/landing-a-php-job-part-3-curriculum-vitae/&quot;&gt;Part
3: Curriculum Vitae&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Review: Deep Fried Bytes Podcast</title>
      <link>http://davedevelopment.co.uk/2008/08/12/review-deep-fried-bytes-podcast.html</link>
      <pubDate>Tue, 12 Aug 2008 19:58:30 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/08/12/review-deep-fried-bytes-podcast</guid>
      <description>&lt;p&gt;[caption id=&quot;attachment_92&quot; align=&quot;alignnone&quot; width=&quot;300&quot; caption=&quot;Deep Fried Bytes&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/08/deepfried_text_300px.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/08/deepfried_text_300px.png&quot; alt=&quot;Deep Fried Bytes&quot; title=&quot;Deep Fried Bytes&quot; width=&quot;300&quot; height=&quot;122&quot; class=&quot;size-medium wp-image-92&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;As previously &lt;a href=&quot;http://davedevelopment.co.uk/2008/06/03/software-development-podcasts/&quot;&gt;noted&lt;/a&gt;, I've been listening to a lot of podcasts recently, here's my first review&lt;/p&gt;




&lt;blockquote&gt;&lt;a href=&quot;http://deepfriedbytes.com/&quot;&gt;Deep Fried Bytes&lt;/a&gt; is an audio talk show with a Southern flavor hosted by technologists and developers &lt;a href=&quot;http://keithelder.net/blog/&quot;&gt;Keith Elder&lt;/a&gt; and &lt;a href=&quot;http://blog.cloudsocket.com/&quot;&gt;Chris Woodruff&lt;/a&gt;. The show discusses a wide range of topics including application development, operating systems and technology in general. Anything is fair game if it plugs into the wall or takes a battery.&lt;/blockquote&gt;




&lt;p&gt;The first thing I'll say about this podcast is that it's fun! The goofy intro music and southern accents are a breath of fresh air, especially for me being over on this side of the pond. &lt;/p&gt;




&lt;p&gt;Woody and Keith never seem short of questions to ask and usually keep their guests engaged, often making them work pretty hard to explain their points. They make a point asking their guests to back track a little, getting them to give their slant on an acronym or buzz word that they have used.&lt;/p&gt;




&lt;p&gt;Considering I'm an &lt;a href=&quot;http://en.wikipedia.org/wiki/Open_source_advocacy&quot;&gt;open source advocate&lt;/a&gt;, I've been pleasantly surprised to have enjoyed all the .net topics that have come up. While Deep Fried Bytes wants to be a &lt;em&gt;Technology Podcast&lt;/em&gt;, as Keith and Woody are both currently .net guys, lots of their discussions and guests are based around Microsoft technologies. I think of the 9 episodes so far, only &lt;a href=&quot;http://deepfriedbytes.com/podcast/deep-fried-bytes-episode-4-scaling-large-web-sites-with-joe-stump-lead-architect-at-digg/&quot;&gt;episode 4&lt;/a&gt; with Joe Stump of &lt;a href=&quot;http://www.digg.com&quot;&gt;Digg&lt;/a&gt; fame, has not involved some sort of Microsoft employee or MVP. This may be enough to put some non-Microsoft fans off, but I'd advise against it. Like I said, the shows are very interesting, good fun and might even give someone like me a little insight on what it's like on the Microsoft side of the fence.&lt;/p&gt;




&lt;p&gt;Another thing worth mentioning, the podcasts usually have a sponsor, it currently plays for about 10 seconds part way through the cast, is fairly unobtrusive and isn't annoying or aggravating.&lt;/p&gt;




&lt;h2&gt;Conclusion&lt;/h2&gt;


&lt;p&gt;Definitely worth a subscription, doubt you will be disappointed. 8/10&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Review: Gliffy.com</title>
      <link>http://davedevelopment.co.uk/2008/08/11/review-gliffycom.html</link>
      <pubDate>Mon, 11 Aug 2008 11:23:06 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/08/11/review-gliffycom</guid>
      <description>&lt;p&gt;[caption id=&quot;attachment_72&quot; align=&quot;alignleft&quot; width=&quot;188&quot; caption=&quot;Gliffy.com&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/08/logo_index.gif&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/08/logo_index.gif&quot; alt=&quot;Gliffy.com&quot; title=&quot;Gliffy Logo&quot; width=&quot;188&quot; height=&quot;70&quot; class=&quot;size-medium wp-image-72&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;I've been using &lt;a href=&quot;http://www.gliffy.com&quot;&gt;gliffy.com&lt;/a&gt; for quite some time now and after recently signing up for a company licence, I thought I'd share my thoughts on it. This is far from a complete review, just some of the reasons we're making good use of it.&lt;/p&gt;




&lt;blockquote&gt;Gliffy.com is a free web-based diagram editor. Create and share flowcharts, network diagrams, floorplans, user interface designs and other drawings online.&lt;/blockquote&gt;




&lt;p&gt;Firstly, I've used many open source tools for drawing diagrams, particularly &lt;a href=&quot;http://en.wikipedia.org/wiki/Unified_Modeling_Language&quot;&gt;&lt;accronym title=&quot;Unified Modelling Language&quot;&gt;UML&lt;/accronym&gt;&lt;/a&gt; diagrams and they all have their drawbacks. Some of them do particular things really well, but all have ended up not quite &lt;a href=&quot;http://www.phrases.org.uk/meanings/cut-the-mustard.html&quot;&gt;cutting the mustard&lt;/a&gt;, although some of these projects may have come along way since I've used them. To name a few, I've used:&lt;/p&gt;


&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://argouml.tigris.org/&quot;&gt;ArgoUML&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.gnome.org/projects/dia/&quot;&gt;Dia&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.koffice.org/kivio/&quot;&gt;Kivio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Diagram types&lt;/h2&gt;


&lt;p&gt;[caption id=&quot;attachment_80&quot; align=&quot;alignnone&quot; width=&quot;94&quot; caption=&quot;UML Shapes&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot3.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot3.png&quot; alt=&quot;UML Shapes&quot; title=&quot;UML Shapes&quot; width=&quot;94&quot; height=&quot;300&quot; class=&quot;size-medium wp-image-80&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;Next up, what do I need a diagram tool for? Most of the diagrams I draw are very simple. I draw small &lt;a href=&quot;http://en.wikipedia.org/wiki/Class_diagram&quot;&gt;class diagrams&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Sequence_diagram&quot;&gt;sequence diagrams&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Use_case_diagram&quot;&gt;use case diagrams&lt;/a&gt;, simple &lt;a href=&quot;http://en.wikipedia.org/wiki/Flowchart&quot;&gt;flow charts&lt;/a&gt; and the odd &lt;a href=&quot;http://en.wikipedia.org/wiki/Network_diagram&quot;&gt;network diagram&lt;/a&gt;. Gliffy provides a reasonable collection of shapes and icons for all of these diagram types, which you can simply drag and drop on to your canvas. The gliffy &lt;a href=&quot;http://www.gliffy.com/examples/&quot;&gt;examples&lt;/a&gt; page includes a &lt;a href=&quot;http://www.gliffy.com/examples/uml/&quot;&gt;class diagram&lt;/a&gt; and a &lt;a href=&quot;http://www.gliffy.com/examples/network-diagrams/&quot;&gt;network diagram&lt;/a&gt;, both showing these predefined shapes.&lt;/p&gt;




&lt;h2&gt;Collaboration&lt;/h2&gt;


&lt;p&gt;At my workplace, we need to collaborate on diagrams. We have multiple platforms in use (2 linux, 4 windows), so whatever file format we use must be accessible to all developers. As a desirable, it would be nice if the format was none binary, so we can see the difference between revisions in the subversion repository. &lt;/p&gt;


&lt;p&gt;[caption id=&quot;attachment_76&quot; align=&quot;alignnone&quot; width=&quot;300&quot; caption=&quot;Gliffy Flowchart&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot1.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot1.png&quot; alt=&quot;Gliffy Flowchart&quot; title=&quot;Gliffy Flowchart&quot; width=&quot;300&quot; height=&quot;159&quot; class=&quot;size-medium wp-image-76&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;Gliffy.com provides export to JPEG, PNG and SVG formats. For those not in the know, &lt;a href=&quot;http://www.w3.org/Graphics/SVG/&quot;&gt;&lt;accronym title=&quot;Scalable Vector Graphics&quot;&gt;SVG&lt;/accronym&gt;&lt;/a&gt; is a standards based xml format for storing vector graphics. I tried the SVG export and opened the file up in &lt;a href=&quot;http://www.inkscape.org/&quot;&gt;Inkscape&lt;/a&gt; and was very impressed with the export. As you would hope, all &lt;em&gt;objects&lt;/em&gt; in the diagram were editable, including the text. The actual diagram I exported had an embedded image in, so Gliffy exported the diagram as SVG and included it with the image in a zip file, which also worked great. Another benefit, SVG is an xml format, we can stick the exports in the Subversion repository and diffs work great. One dissapointing part of gliffy, is you can't upload SVG files to edit, so we have to stick with gliffy itself to make major changes, Inkscape for touch ups etc. This is probably a compatibility issue, the complete SVG specification is probably very difficult to implement.&lt;/p&gt;


&lt;p&gt;[caption id=&quot;attachment_77&quot; align=&quot;alignnone&quot; width=&quot;260&quot; caption=&quot;Gliffy diagram in Inkscape&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot2.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot2.png&quot; alt=&quot;Gliffy diagram in Inkscape&quot; title=&quot;Inkscape&quot; width=&quot;260&quot; height=&quot;300&quot; class=&quot;size-medium wp-image-77&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;File formats aside, gliffy provides shared storage for your diagrams, allowing colleagues to work on diagrams created by you. It also stores a revision history for you.&lt;/p&gt;




&lt;h2&gt;Usability&lt;/h2&gt;


&lt;p&gt;[caption id=&quot;attachment_79&quot; align=&quot;alignnone&quot; width=&quot;300&quot; caption=&quot;Gliffy Edit Menu&quot;]&lt;a href=&quot;http://davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot4.png&quot;&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/08/screenshot4.png&quot; alt=&quot;Gliffy Edit Menu&quot; title=&quot;Gliffy Edit Menu&quot; width=&quot;300&quot; height=&quot;211&quot; class=&quot;size-medium wp-image-79&quot; /&gt;&lt;/a&gt;[/caption]&lt;/p&gt;

&lt;p&gt;Gliffy provides the typical editor capabilities, copy, paste, cut, delete and undo, so most people should feel right at home, though I aren't sure how well the keyboard shortcuts work. I use it with &lt;a href=&quot;http://www.getfirefox.com&quot;&gt;FireFox 3&lt;/a&gt; on &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu&lt;/a&gt; and the described shortcuts don't seem to work.&lt;/p&gt;




&lt;p&gt;Aside from that, it's the regular run of the mill, drag and drop objects where you want them. It feels smooth enough, drop it in something like &lt;a href=&quot;http://wiki.mozilla.org/Prism&quot;&gt;Prism&lt;/a&gt; and you probably wouldn't be able to tell it's a web app. One small gripe, if you have joined objects with the connector tool and then move the objects around, sometimes the connector flips it's angle.&lt;/p&gt;




&lt;h2&gt;Support&lt;/h2&gt;


&lt;p&gt;Worth mentioning, we've made two support requests and both were dealt with very promptly and efficiently. The first was creating a new billing account for our free trial under a different username and the second was one of my colleagues asking for some diagrams transferring from his personal account to his company one.&lt;/p&gt;




&lt;h2&gt;Value&lt;/h2&gt;


&lt;p&gt;At $25 a month for 10 users, Gliffy provides a excellent &lt;accronym title=&quot;Return on investment&quot;&gt;ROI&lt;/accronym&gt; for our company. For our six developers, &lt;a href=&quot;http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.co.uk%2FMicrosoft-D86-02751-Visio-2007-PC%2Fdp%2FB000HCZ8GC%3Fie%3DUTF8%26s%3Delectronics%26qid%3D1217974867%26sr%3D8-1&amp;tag=davedvd-21&amp;linkCode=ur2&amp;camp=1634&amp;creative=6738&quot;&gt;Visio Standard&lt;/a&gt; would set us back a one off cost of 1079.88 GBP. 1079.88 GBP would buy us gliffy for 10 users, for just over 7 years. It's cross platform, accessible from anywhere where you have a web browser and an internet connection. Enough said.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Getting the right chair</title>
      <link>http://davedevelopment.co.uk/2008/08/09/getting-the-right-chair.html</link>
      <pubDate>Sat, 09 Aug 2008 13:04:24 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/08/09/getting-the-right-chair</guid>
      <description>&lt;p&gt;Just over a week ago, I listened to &lt;a href=&quot;http://www.joelonsoftware.com/&quot;&gt;Joel Spolsky&lt;/a&gt; and &lt;a href=&quot;http://www.codinghorror.com/&quot;&gt;Jeff Atwood&lt;/a&gt; &lt;a href=&quot;http://blog.stackoverflow.com/2008/07/podcast-16/&quot;&gt;talking about chairs&lt;/a&gt; in their weekly &lt;a href=&quot;http://www.stackoverflow.com&quot;&gt;stackoverflow&lt;/a&gt; podcast. Just yesterday, my manager did a sweep of our office asking if people are happy with their chairs, because one person had asked for a new one. My existing chair was actually broken so I asked for a replacement.&lt;/p&gt;

&lt;p&gt;I previously read articles by both &lt;a href=&quot;http://www.codinghorror.com/blog/archives/001146.html&quot;&gt;Jeff&lt;/a&gt; and &lt;a href=&quot;http://www.joelonsoftware.com/articles/FieldGuidetoDevelopers.html&quot;&gt;Joel&lt;/a&gt; about equipping developers with a fancy chair and while I don't think they're wrong, having considered it, I still don't think I fit into that category. If I get uncomfortable at work, it's because I just spent 40 minutes playing football in my lunch break, don't want any more time to slip, so I skip getting a shower. Or I feel uncomfortable because we don't have air conditioning.&lt;/p&gt;

&lt;p&gt;That said, even if I did decide I wanted a fancy chair, I doubt my company would see fit to buy me an &lt;a href=&quot;http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FAeron-Chair-Adjustable-Posture-Pellicle%2Fdp%2FB0006NUB5U%3Fie%3DUTF8%26s%3Doffice-products%26qid%3D1218286732%26sr%3D8-1&amp;tag=davedvd-21&amp;linkCode=ur2&amp;camp=1634&amp;creative=6738&quot;&gt;aeron&lt;/a&gt;. Maybe if I'd been spoilt at some point, I'd come to realise the value of a quality chair, for now I'll just settle with the one my colleague is unhappy with.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A step in the right direction</title>
      <link>http://davedevelopment.co.uk/2008/07/15/a-step-in-the-right-direction.html</link>
      <pubDate>Tue, 15 Jul 2008 21:42:17 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/07/15/a-step-in-the-right-direction</guid>
      <description>&lt;p&gt;At my current workplace, on a particular project we have not been allowed to use third party libraries, due to fears of licensing issues if and when we come to sell the product. The project is predominantly for the business, but it would be nice if we could convert the product into something we could market.&lt;/p&gt;

&lt;p&gt;Despite multiple discussions and suggesting to management that open source software licensed under an &lt;a href=&quot;http://en.wikipedia.org/wiki/MIT_License&quot;&gt;MIT&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/BSD_license&quot;&gt;BSD&lt;/a&gt; license would not have any implications, they would not have it. This has meant writing pretty much everything we need from scratch.&lt;/p&gt;

&lt;p&gt;Recently, the managing director must have noticed the improved the user experience the little bit of JavaScript we use brings to the product. In previous conversations, I've mentioned to the MD that JavaScript is an area that the development team has little experience with, and this seems to have nudged him into letting us use a third party library or tool kit within the product. I spent a bit of time reviewing some of the frameworks and tool kits out there and basically boiled down to going with &lt;a href=&quot;http://dojotoolkit.org/&quot;&gt;Dojo&lt;/a&gt;. Most of the frameworks reviewed provide similar features, Dojo came up on top because of the BSD license, recent announcement of a &lt;a href=&quot;http://dojotoolkit.org/2008/05/21/announcing-zend-framework-integration-dojo-1-x-0&quot;&gt;partnership&lt;/a&gt; with the &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; and the added bonus of contributors having to sign a &lt;a href=&quot;http://dojotoolkit.org/cla&quot;&gt;CLA&lt;/a&gt;. Looking forward to getting stuck into it and making our application a little easier on the eye.&lt;/p&gt;

&lt;p&gt;The next task is to go about documenting the best way to include and use the tool kit in our application, will write about it if I get chance.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Zend PHP 5 Certified Engineer</title>
      <link>http://davedevelopment.co.uk/2008/07/15/zend-php-5-certified-engineer.html</link>
      <pubDate>Tue, 15 Jul 2008 21:11:01 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/07/15/zend-php-5-certified-engineer</guid>
      <description>&lt;p&gt;After putting the exam off continuously for about 18 months, I actually got around to taking my &lt;a href=&quot;http://www.zend.com/en/services/certification/&quot;&gt;Zend PHP 5 Certification&lt;/a&gt; exam. I originally scheduled the exam, put it off for a few months, then actually forgot about the exam altogether, only to reminded by &lt;a href=&quot;http://www.google.com/calendar&quot;&gt;google calendar&lt;/a&gt; an hour before I was due to take it. The test centre was at least an hour away, so that was a waste of $125. I scheduled the exam again, kept putting it off until I caved in last month and got it done.&lt;/p&gt;

&lt;p&gt;The exam itself was considerably harder than the original, I wasn't all that confident when I clicked the 'End Exam' button, but I got the job done. I'm glad I found it harder, I've obviously improved my knowledge of PHP since I took the original exam nearly 3 years, so they must have made the certification more difficult to achieve.&lt;/p&gt;

&lt;p&gt;As far preparation goes, I read the &lt;a href=&quot;http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.co.uk%2Farchitects-Zend-Certification-Study-Guide%2Fdp%2F0973862149%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1216156011%26sr%3D8-1&amp;tag=davedvd-21&amp;linkCode=ur2&amp;camp=1634&amp;creative=6738&quot;&gt;study guide&lt;/a&gt; right through once, making notes along the way. I turned up at the test centre about 20 minutes early and went through my notes. The study guide clearly did a good job!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.zend.com/store/education/certification/authenticate.php?ClientCandidateID=ZEND002622&amp;amp;RegistrationID=212933867&quot; title=&quot;Zend Certified Engineer Authentication&quot;&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;img src=&quot;http://davedevelopment.co.uk/wp-content/uploads/php5_zce_logo.gif&quot; alt=&quot;Zend Certified Engineer&quot; width=&quot;73&quot; height=&quot;50&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Processing output with SimpleXML</title>
      <link>http://davedevelopment.co.uk/2008/07/08/processing-output-with-simplexml.html</link>
      <pubDate>Tue, 08 Jul 2008 11:13:36 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/07/08/processing-output-with-simplexml</guid>
      <description>&lt;p&gt;PHP's output buffering allows you to register &lt;a href=&quot;http://uk.php.net/callback&quot;&gt;callbacks&lt;/a&gt;, that will process the output before returning it back up the stack. This feature is usually used in conjunction with handlers added by PHP or it's extensions such as &lt;a href=&quot;http://uk3.php.net/manual/en/function.ob-gzhandler.php&quot;&gt;ob_gzhandler&lt;/a&gt;, which &lt;a href=&quot;http://www.gzip.org/&quot;&gt;gzips&lt;/a&gt; the output, or &lt;a href=&quot;http://uk2.php.net/manual/en/function.ob-tidyhandler.php&quot;&gt;ob_tidyhandler&lt;/a&gt;, which passes the output through &lt;a href=&quot;http://tidy.sourceforge.net/&quot;&gt;tidy&lt;/a&gt;. As output buffers can be stacked, you can use many handlers in turn using the &lt;a href=&quot;http://uk3.php.net/ob_start&quot;&gt;ob_start&lt;/a&gt; function.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php 

ob_start('ob_gzhandler');
ob_start('ob_tidyhandler');

?&amp;gt;
&amp;lt;!-- Your output here --&amp;gt;
&amp;lt;/pre&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because you can pass ob_start any function name you desire, adding custom handlers is easy. At my current workplace, we needed a quick fix for something we'd overlooked and because we'd (fairly) strictly stuck to generate decent markup, we used an output handler in combination with &lt;a href=&quot;http://uk2.php.net/simplexml&quot;&gt;SimpleXml&lt;/a&gt; to manipulate the &lt;acronym title=&quot;Document Object Model&quot;&gt;DOM&lt;/acronym&gt; in our &lt;acronym title=&quot;eXtensible HyperText Markup Language&quot;&gt;HTML&lt;/acronym&gt; pages. I can't divulge the what we needed to do or the details of how we did it, but here's a basic example that will attempt to insert a &lt;acronym title=&quot;Cascading StyleSheet&quot;&gt;CSS&lt;/acronym&gt; link to a page.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php 
function process_output($buffer)
{
    try {
        $xml = new SimpleXmlElement($buffer);
        if (isset($xml-&amp;gt;head)) {
            $link = $xml-&amp;gt;head-&amp;gt;addChild('link');
            $link-&amp;gt;addAttribute('rel', 'stylesheet');
            $link-&amp;gt;addAttribute('href', 'http://o.aolcdn.com/dojo/1.0/dojo/resources/dojo.css');
            $link-&amp;gt;addAttribute('type', 'text/css');
        }
        return $xml-&amp;gt;asXML();
    } catch(Exception $e) {
        error_log($e-&amp;gt;getMessage());
        return false;
    }
}

ob_start('process_output');

?&amp;gt;
&amp;lt;!-- Your output here --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This code can be added to a file that's included in every page for a quick fix, but beware of performance hits. A quick test showed adding the above processing dropped this &lt;a href=&quot;/wp-content/uploads/output_processing.phps&quot;&gt;example files&lt;/a&gt; performance from 960 requests per second to 795 requests per second.&lt;/p&gt;



</description>
    </item>
    
    <item>
      <title>Fat Models and the Data Access Layer</title>
      <link>http://davedevelopment.co.uk/2008/06/17/fat-models-and-the-data-access-layer.html</link>
      <pubDate>Tue, 17 Jun 2008 20:57:12 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/06/17/fat-models-and-the-data-access-layer</guid>
      <description>&lt;p&gt;There's been some discussion recently on why active record:&lt;/p&gt;


&lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;http://kore-nordmann.de/blog/why_active_record_sucks.html&quot;&gt;Sucks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.mikeseth.com/index.php?/archives/4-ActiveRecord-sucks,-but-Kore-Nordmann-is-wrong.html&quot;&gt;Sucks - but not like that&lt;/a&gt;;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://karwin.blogspot.com/2008/05/activerecord-does-not-suck.html&quot;&gt;Doesn't suck&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;I like the active record pattern, so I don't think it sucks, but I do think it's used a little out of context sometimes. &lt;/p&gt;




&lt;p&gt;If you're building a small lightweight app, then I think using your &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_access_layer&quot;&gt;Data access layer&lt;/a&gt; as the M in &lt;a href=&quot;http://en.wikipedia.org/wiki/Model-view-controller&quot;&gt;MVC&lt;/a&gt; is a logical thing to do. It's quick, it's easy and you can extend either your &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/ActiveRecord&quot;&gt;active record&lt;/a&gt; in &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Rails&lt;/a&gt;, or extend your &lt;a href=&quot;http://framework.zend.com/manual/en/zend.db.table.html&quot;&gt;Table DataGateway&lt;/a&gt; in the &lt;a href=&quot;http://framework.zend.com&quot;&gt;Zend Framework&lt;/a&gt; and you wont go far wrong.&lt;/p&gt;




&lt;p&gt;As soon as your app gets a little more complex, you might want to start creating custom
models that contain more business logic than simply pulling and pushing to the database. If your application is complex enough, chances are your model will need to interact with more than one database table, if not database, so at this point, like Bill Karwin pointed out, your model should be &lt;em&gt;using&lt;/em&gt; the DAL, not &lt;em&gt;being&lt;/em&gt; the DAL. Loosening the coupling between model and DAL, should also help with automated testing the business logic, in that mock objects could replace the DAL. &lt;/p&gt;




&lt;p&gt;The only problem is, I don't know the best way to do it.&lt;/p&gt;




&lt;p&gt;I'm currently learning the ways of the Zend Framework and would be interested to see how people think the best way to implement this kind of complex model. I'm currently leaning toward something like this. I've included a &lt;a href=&quot;http://framework.zend.com/manual/en/zend.form.html&quot;&gt;Zend_Form&lt;/a&gt; object, to show how the &lt;tt&gt;Persons&lt;/tt&gt; model encapsulates more logic than just pushing to and from the database. I think the biggest benefit of Zend_Form is validating input, which I consider domain logic, so should be part of the model. But I'm not sure the best way to make things easily testable, without pushing into the realms of fancy &lt;a href=&quot;http://martinfowler.com/articles/injection.html&quot;&gt;Dependency Injection&lt;/a&gt; and what not, which I'm not all that familiar with.&lt;/p&gt;




&lt;p&gt;File: application/models/Persons.php&lt;/p&gt;


&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
&amp;lt;?php

class Persons
{
    public function findByEmail($email)
    {
        $table  = self::getTable();
        $select = $table-&gt;select()
                        -&gt;where('email = ?', $email);
        return $table-&gt;fetchAll($select);
    }

    public static function getTable()
    {
        // add some dependency injection?
        return new Persons_Table();
    }   

    public static function getForm()
    {
        // add some dependency injection?
        return new Persons_Form();
    }

    // ...
}
&lt;/pre&gt;




&lt;p&gt;File: application/models/Persons/Table.php&lt;/p&gt;


&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
&amp;lt;?php

class Persons_Table extends Zend_Db_Table
{
    protected $_name = 'persons';

    // ...
}
&lt;/pre&gt;




&lt;p&gt;File: application/models/Persons/Form.php&lt;/p&gt;


&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
&amp;lt;?php

class Persons_Form extends Zend_Form
{
    // ...
}
&lt;/pre&gt;




&lt;p&gt;At first it may seem that the &lt;tt&gt;Persons&lt;/tt&gt; model just ends up acting as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Proxy_pattern&quot;&gt;proxy&lt;/a&gt; to the &lt;tt&gt;Persons_Form&lt;/tt&gt; and &lt;tt&gt;Persons_Table&lt;/tt&gt;, but once you start writing methods that use both together, you'll start seeing fatter models and thin controllers, which is all good.&lt;/p&gt;




&lt;p&gt;This really is a request for comments really, as I'm personally not sure about the best way to go about this. Would be interesting if any of the people using the MVC part of the Zend Framework in the real world go about this?&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Software development podcasts</title>
      <link>http://davedevelopment.co.uk/2008/06/03/software-development-podcasts.html</link>
      <pubDate>Tue, 03 Jun 2008 22:30:38 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/06/03/software-development-podcasts</guid>
      <description>&lt;p&gt;I recently picked myself up an &lt;a href=&quot;http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.co.uk%2FNew-Apple-iPod-nano-black%2Fdp%2FB000OY71OA%3Fie%3DUTF8%26s%3Delectronics%26qid%3D1212531522%26sr%3D8-1&amp;tag=davedvd-21&amp;linkCode=ur2&amp;camp=1634&amp;creative=6738&quot;&gt;8GB Ipod Nano&lt;/a&gt;, I spend a fair bit of time walking my little dog Murphy and I've found it great for both music and more recently &lt;a href=&quot;http://en.wikipedia.org/wiki/Podcast&quot;&gt;podcasts&lt;/a&gt;. So much so, that I quickly got few to the few podcasts I was subscribed to, so went in search of more. I've listened to and liked very much:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;PHP Podcasts &lt;a href=&quot;http://feeds.feedburner.com/PhpPodcasts&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;/li&gt;&lt;li&gt;Stack Overflow &lt;a href=&quot;http://blog.stackoverflow.com/index.php?feed=podcast&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The new editions to my list are:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Audible Ajax &lt;a href=&quot;http://media.ajaxian.com/&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Code Sermon &lt;a href=&quot;http://www.codesermon.org/portals/15/podcast.xml&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Google Developer Podcast &lt;a href=&quot;http://feeds.feedburner.com/GoogleDeveloperPodcast&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;WebDevRadio &lt;a href=&quot;http://feeds.feedburner.com/WebdevradioPodcastHome&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;The Web 2.0 Show &lt;a href=&quot;http://feeds.feedburner.com/web20Show&quot;&gt;rss&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I'll pipe back in a couple of weeks and give my thoughts on the new ones.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Switching server environments</title>
      <link>http://davedevelopment.co.uk/2008/05/26/switching-server-environments.html</link>
      <pubDate>Mon, 26 May 2008 08:24:33 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/05/26/switching-server-environments</guid>
      <description>&lt;p&gt;After reading John Rockefeller's post on &lt;a href=&quot;http://www.johnrockefeller.net/?p=194&quot;&gt;Handling multiple domains&lt;/a&gt; and less recently Richard Heye's post on &lt;a href=&quot;
Displaying errors&quot;&gt;displaying errors&lt;/a&gt;, I thought I'd write a little post about my qualms with their methods.&lt;/p&gt;




&lt;p&gt;I won't go into too much detail, but both examples use a variable that can be manipulated by the user, &lt;tt&gt;$_SERVER['HTTP_HOST']&lt;/tt&gt;. Richard actually changed his example to use &lt;tt&gt;$_SERVER['SERVER_NAME']&lt;/tt&gt;, but as Chris Shiflett &lt;a href=&quot;http://shiflett.org/blog/2006/mar/server-name-versus-http-host&quot;&gt;shows&lt;/a&gt;, neither are guaranteed to be genuine.&lt;/p&gt;




&lt;p&gt;My example relies on having access to the server configuration, but is fairly simple. I think &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; uses a similar method.&lt;/p&gt;




&lt;p&gt;First we set up our virtual hosts, all pointing to the same codebase, but each getting an individual environment variable set using &lt;a href=&quot;http://httpd.apache.org/docs/2.0/mod/mod_env.html&quot;&gt;mod_env&lt;/a&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;
    ServerName davedevelopment.co.uk
    DocumentRoot /var/www/codebase
    SetEnv WEB_ENV davedevelopment.co.uk
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:80&amp;gt;
    ServerName test.davedevelopment.co.uk
    DocumentRoot /var/www/codebase
    SetEnv WEB_ENV test.davedevelopment.co.uk
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:80&amp;gt;
    ServerName anotherSite.com
    DocumentRoot /var/www/codebase
    SetEnv WEB_ENV another_site
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code then switches on this variable, which should be guaranteed to be controlled by yourself?&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt;?php
switch($_SERVER['WEB_ENV']) {
    case 'davedevelopment.co.uk':
        $message = 'Welcome to DaveDevelopment';
        break;
    case 'another_site':
        $message = 'Welcome to another site';
        break;
    case 'test.davedevelopment.co.uk':
    default:
        $message = 'Welcome to DaveDevelopment Test';
        break;
}

echo $message;

?&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Being a Lead Developer - Part 3 - The Team</title>
      <link>http://davedevelopment.co.uk/2008/05/23/being-a-lead-developer-part-3-the-team.html</link>
      <pubDate>Fri, 23 May 2008 21:46:18 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/05/23/being-a-lead-developer-part-3-the-team</guid>
      <description>&lt;p&gt;This mini-series is focusing on my experiences in my first Lead Developer role. Last time out I talked about the &lt;a href=&quot;http://davedevelopment.co.uk/2008/05/19/being-a-lead-developer-part-2-software-tools-and-methods/&quot; title=&quot;Software tools and methods&quot;&gt;tools and methods&lt;/a&gt; I've introduced since taking on the role, this post is going to discuss any impact I've had on the team.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Laugh and Learn culture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Something I've tried to encourage within the team is to laugh at each others expense. This sounds bad, but I'm sure it helps lift morale and in turn we &lt;em&gt;all&lt;/em&gt; learn from each others mistakes. It's not to say that we actively encourage mistakes, but everyone usually finds out when someone's written a &lt;a href=&quot;http://www.thedailywtf.com&quot;&gt;WTF?&lt;/a&gt; piece and it may even make it to the wall of shame. I don't know if this will turn round and bite me in the arse because somebody complains about being bullied, but it seems to be okay so far.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Professionalism&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the new methods and tools we've recently introduced, I feel like we're starting to act like a proper development team and we're doing less of the gun slinging. I hope this is making people 'feel' like they are part of a proper development team, which should improve morale. On the flip side, I've been getting everyone to take the piss out of one another, which may be frowned upon, but I don't think that should be the case in a young industry.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Passion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is something we particularly lack in the team, the developers get little creative freedom and tend to lack any sort of passion when developing. &lt;blockquote&gt;&quot;We need the developers thinking about their work when they're in the shower&quot;&lt;/blockquote&gt; Basically, we're developing a system that will serve a great purpose for the company, but it's just not all that fun to develop. I've been lucky enough to take on some smaller projects, where I've had creative freedom, or I've gone ahead and created some projects of my own that have been useful as a learning tool and in the end provided the team with a useful tool. For example I wrote a simple daemon in ruby that watches log files, sending any output in bursts to a &lt;a href=&quot;http://www.jabber.org/&quot;&gt;jabber&lt;/a&gt; chat room. I'm not saying work should be fun all the time, but a little freedom can keep the work force happy and &lt;a href=&quot;http://en.wikipedia.org/wiki/Google#Innovation_time_off&quot;&gt;greatly benefit the company&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Being a Lead Developer - Part 2 - Software Tools and methods</title>
      <link>http://davedevelopment.co.uk/2008/05/19/being-a-lead-developer-part-2-software-tools-and-methods.html</link>
      <pubDate>Mon, 19 May 2008 19:43:06 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/05/19/being-a-lead-developer-part-2-software-tools-and-methods</guid>
      <description>&lt;p&gt;This series is based on my experiences as a Lead Developer. The first part covered &lt;a href=&quot;http://davedevelopment.co.uk/2008/05/17/being-a-lead-developer-part-1-mentoring-trainees/&quot;&gt;being a mentor&lt;/a&gt;, this part is going to focus on the tools and methods I introduced to the team in the last eight months.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Software tools and methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A previous post on &lt;a href=&quot;http://davedevelopment.co.uk/2008/03/20/10-tools-for-modern-php-development/&quot;&gt;modern tools&lt;/a&gt; pretty much sums up the tools I've introduced to our team, the ones listed here are the ones that have been successful. To be honest, this sounds like a big list of buzz terms, tools and methods, but I can testify that these methods have helped improve our development environment.&lt;/p&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated build, configuration and migration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We wanted a way to get the application up and running fairly swiftly in development environments and also a way of deploying code to testing, staging and production environments. I developed &lt;a href=&quot;http://phing.info&quot;&gt;phing&lt;/a&gt; scripts to retrieve code from the &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;subversion&lt;/a&gt; repository, configure it and then create/update the database. I feel this was successful, the scripts do what we need and as you'll see lead on to better things.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Continuous Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once we had automated builds in place, it made sense to get some continuous integration going. Initially it was with vanilla &lt;a href=&quot;http://cruisecontrol.sourceforge.net/&quot;&gt;CruiseControl&lt;/a&gt;, but later switched to &lt;a href=&quot;http://www.phpundercontrol.org/&quot;&gt;phpundercontrol&lt;/a&gt;. I consider this a success from the developers point of few, particularly because mistakes made with database schema updates or procedures are quickly highlighted. On the other side, the managers haven't really embraced having a 'cutting edge' version of the application running and have pretty much ignored it. This may because of the dataset the database has, but that could easily be changed.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Unit Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is definitely one of the most effective tools I've introduced and our collection of tests is growing. Originally I wrote a few unit tests for my own code using &lt;a href=&quot;http://phpunit.de&quot;&gt;phpunit&lt;/a&gt;, but then started to encourage the other developers to have a go. One way in which I achieved this was to introduce the developers to writing tests for very easy classes/methods. We have alot of &lt;a href=&quot;http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html&quot;&gt;transfer object&lt;/a&gt; classes with various getters/setters, so to get them started I generated skeleton test classes for the value object classes and asked them to fill the gaps, even getting the trainees in on the act. Now everybody understands what the unit tests are for and how to go about writing them and we even uncovered a couple of mistakes in the transfer objects. Hopefully this will encourage the developers to not only write tests, but try to write code that &lt;em&gt;can&lt;/em&gt; be tested in this way, along the low &lt;a href=&quot;http://en.wikipedia.org/wiki/Coupling_(computer_science)&quot;&gt;coupling&lt;/a&gt;, high &lt;a href=&quot;http://en.wikipedia.org/wiki/Cohesion_%28computer_science%29&quot;&gt;cohesion&lt;/a&gt; track. Again, I see this as being a success with the developers, but will probably find managers questioning it's usefulness.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Scrums/Stand up meetings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Part of my job requires that I anticipate problems in meeting deadlines on the development plan, to deal with this I introduced daily &lt;a href=&quot;http://en.wikipedia.org/wiki/Stand-up_meeting&quot;&gt;stand up meetings&lt;/a&gt;. Initially people, myself included, found it hard to focus on the three basic questions...&lt;/p&gt;


&lt;ul&gt;
    &lt;li&gt;What did I do yesterday?&lt;/li&gt;
    &lt;li&gt;What stopped me achieving all I wanted to?&lt;/li&gt;
    &lt;li&gt;What will I be doing today?&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;... but in the end we started to get going and I think everybody found them moderately useful. This went a little wayward when our little meeting room got taken over for a period of time, but then we started running the scrums in a chat room. Not only did this make it easier for everybody, we didn't all have to do it at the same time, but it stopped us getting carried away with things and also everything was logged. I can look back through the logs to see what we said at the scrum three Fridays ago etc.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Peer Code Reviews&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was quite a no brainer, it helps spot mistakes or code that's not quite up to standards. I basically wrote a ruby hook for the subversion repository that emails a random developer asking to run a code review on every fifth commit. I also involved the trainees, so they get to review code the full time developers are writing for the main system, giving them a little insight into the applications codebase. These have been successful and the team confirmed this in a recent meeting.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Scheduling and Estimates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've tried to encourage the developers to generate and provide better estimates for their workload to the managers with mixed success. Despite trying to explain the benefits of using a simple &lt;a href=&quot;http://www.joelonsoftware.com/articles/fog0000000245.html&quot;&gt;estimating technique&lt;/a&gt;, only two developers have taken to it well. I'm happy for the others to generate their own tools and methods for providing estimates, as long as they work.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Being a Lead Developer - Part 1 - Being a mentor</title>
      <link>http://davedevelopment.co.uk/2008/05/17/being-a-lead-developer-part-1-mentoring-trainees.html</link>
      <pubDate>Sat, 17 May 2008 17:13:01 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/05/17/being-a-lead-developer-part-1-mentoring-trainees</guid>
      <description>&lt;p&gt;I got promoted to my current position, Lead Developer, about eight months ago and I've recently been reflecting on what I think I've achieved and what I need to improve on, you can consider these posts thinking out loud. The role was newly created when I was appointed, we previously only had developer roles reporting straight to managers. &lt;/p&gt;




&lt;p&gt;First, a little background on what we are and do. We are a small IT Department, working as a support team for a &lt;a href=&quot;http://www.cspencerltd.co.uk&quot; title=&quot;C Spencer Ltd&quot;&gt;multi-disciplinary engineering contractor&lt;/a&gt;, including development of bespoke systems, mainly web applications. We're currently trying to move all these sub-applications into one big application. We currently employ three developers and two trainee developers. The developers work full time on the main application, while the trainees work through training material and small projects to gain experience. &lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Trainee Developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I first got promoted to the position, the main change to my daily work was being mentor to the trainees. When I started as Lead Developer, we didn't actually have any trainees, but were about to recruit. I was involved in the recruitment process, which was a good experience for me. I had actually asked my manager if I could sit in on a couple of interviews for experience before I got promoted, so I was interested in the aspects of hiring anyway. I did a little background reading on interview techniques [Recommended: &lt;a href=&quot;http://www.joelonsoftware.com/articles/GuerrillaInterviewing3.html&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;http://www.inter-sections.net/2007/11/13/how-to-recognise-a-good-programmer/&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;http://blog.assembleron.com/2007/05/15/interviewing-programmers-101-part-1/&quot;&gt;3&lt;/a&gt;, &lt;a href=&quot;http://blog.assembleron.com/2007/05/21/interviewing-programmers-101-part-2/&quot;&gt;4&lt;/a&gt;, &lt;a href=&quot;http://www.nickhalstead.com/2007/05/23/php-interview-questions-from-yahoo/&quot;&gt;5&lt;/a&gt;], particularly regarding programmers and stuck to the technical side of things, allowing my managers to use their experience to judge the 'people skills'. Things went pretty well, but I'm concerned I probably wont ever do it enough to get good at it. Having said that, I'd rather keep the staff we've got than get really good at recruiting.&lt;/p&gt;




&lt;p&gt;I inherited a training programme and modified it only slightly, except for the module on working as a team, which I rewrote. The trainees work through the programme completing exercises and taking on mini projects along the way. It seems to work pretty well, but I haven't given the actual programme any attention recently and should get it updated, to try and introduce some more modern development techniques.&lt;/p&gt;




&lt;p&gt;The biggest problem I have, is not doing things for the trainees. Whenever they have a problem and ask for help, the temptation is to big up the keyboard and crank out the code they need. This would have benefits, the trainee gets decent code doing what they need and I can get on with my other responsibilities. The downside is, unless the trainee goes back and studies my code, they'll never learn. Instead I need to take my time and coax the answers from the trainee and let them solve their own problems, albeit with a little provoking&lt;/p&gt;




&lt;p&gt;Recently I experimented with our newest trainee, who came to us with little actual programming experience. For his first project, I gave him the choice of implementing it the slightly harder way, which would take him longer but hopefully he would learn more, or the quick and easy way, leaving the harder stuff until later on. Thankfully he chose the hard way and I set him off on his way to use the &lt;a href=&quot;http://framework.zend.com/&quot; title=&quot;Zend Framework&quot;&gt;Zend Framework&lt;/a&gt;. I like the idea of this, I know a lot people find it difficult moving from procedural techniques to object oriented methods, so why bother learning the procedural techniques first? I gave him a pointer by showing him Akra's superb &lt;a href=&quot;http://akrabat.com/zend-framework-tutorial/&quot; title=&quot;Zend Framework Tutorial&quot;&gt;tutorial&lt;/a&gt; and he went from there. On demoing the project to my manager, the trainee was asked &quot;if the system was object oriented?&quot; He replied &quot;No&quot;. He didn't actually know he'd implemented the whole system, barring the view scripts and the boot loaders in object oriented PHP. At first I thought this was bad, thinking he hadn't realised what he was doing the whole time, but maybe it's just that he thought that was just the way things were done. I think this was a success and would be interested to hear how other companies introduce their trainees to frameworks and object oriented principles.&lt;/p&gt;




&lt;p&gt;&lt;a href=&quot;http://davedevelopment.co.uk/2008/05/19/being-a-lead-developer-part-2-software-tools-and-methods/&quot; title=&quot;Software tools and methods&quot;&gt;Part 2 - Software tools and methods&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Log memory usage using declare and ticks in PHP</title>
      <link>http://davedevelopment.co.uk/2008/05/12/log-memory-usage-using-declare-and-ticks-in-php.html</link>
      <pubDate>Mon, 12 May 2008 21:38:06 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/05/12/log-memory-usage-using-declare-and-ticks-in-php</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;See the first comment, looks a far better and more accurate way of tracking memory usage, thanks Mathieu.&lt;/p&gt;




&lt;p&gt;As far as I know, there isn't any memory footprint profiling in &lt;a href=&quot;http://xdebug.org/&quot; title=&quot;Xdebug&quot;&gt;Xdebug&lt;/a&gt;, I think there was at some point but they removed it because it was a little flaky. I like to monitor the memory usage within my scripts, and I've found this simple snippet can help. I don't think it's entirely accurate, but it can help a little. Unfortunately, I don't think it works all that well on Windows, if at all. All good on Linux though.&lt;/p&gt;




&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
&amp;lt;?php

function log_memory() {
    $_SESSION['memory'][] = array(
        'time'   =&amp;gt; microtime(true),
        'memory' =&amp;gt; memory_get_usage(),
    ); // or insert your logging code here
}

declare(ticks = 50); // log every 50 ticks (low level instructions)
register_tick_function('log_memory');
$var = 'a';

for($i=0;$i&amp;lt;100;$i++) {
    $var .= 'a';
}

var_dump($_SESSION['memory']);

?&amp;gt;



&lt;/pre&gt;

</description>
    </item>
    
    <item>
      <title>PHP Versions in popular Linux Distributions</title>
      <link>http://davedevelopment.co.uk/2008/05/08/php-versions-in-popular-linux-distributions.html</link>
      <pubDate>Thu, 08 May 2008 19:33:40 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/05/08/php-versions-in-popular-linux-distributions</guid>
      <description>&lt;p&gt;I had a problem today at work, I've been coding exclusively in PHP5.2 since it was available and most of the servers I've been working for are Debian or Ubuntu based, so I didn't have any problems until this afternoon. We've recently bought a SAN solution from Dell and to gain support we bought two new servers, both with &lt;a href=&quot;http://www.novell.com/products/server/&quot;&gt;SUSE Enterprise Linux&lt;/a&gt; installed, which only comes with PHP 5.1.2. That particular version came out in January 2006. Since then I've been using the new &lt;a href=&quot;http://uk.php.net/manual/en/function.date-create.php&quot;&gt;DateTime&lt;/a&gt; object, the &lt;a href=&quot;http://uk.php.net/filter&quot;&gt;filter&lt;/a&gt; functions, &lt;a href=&quot;http://uk2.php.net/manual/en/function.memory-get-peak-usage.php&quot;&gt;memory_get_peak_usage()&lt;/a&gt; and &lt;a href=&quot;http://uk2.php.net/manual/en/function.sys-get-temp-dir.php&quot;&gt;sys_get_temp_dir()&lt;/a&gt;. And they're only the problems I noticed. We could install from source, but then we lose the subtle benefits of package management.&lt;/p&gt;




&lt;p&gt;So, this lead to me wondering what LAMP versions the popular distros are using, with the help of &lt;a href=&quot;http://distrowatch.com&quot;&gt;DistroWatch&lt;/a&gt;, I compiled this table. It only shows the community/open source distributions, the commercials counterparts for each are usually at least a year behind, guaranteeing support but only for out of date versions.&lt;/p&gt;




&lt;table&gt;
    &lt;tr&gt;
         &lt;th&gt;Distribution&lt;/th&gt;
         &lt;th&gt;Version&lt;/th&gt;
         &lt;th&gt;Apache&lt;/th&gt;
         &lt;th&gt;MySQL&lt;/th&gt;
         &lt;th&gt;PHP&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;Ubuntu&lt;/td&gt;
         &lt;td&gt;8.04 LTS Hardy Heron&lt;/td&gt;
         &lt;td&gt;2.2.8&lt;/td&gt;
         &lt;td&gt;5.0.51a&lt;/td&gt;
         &lt;td&gt;5.2.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;openSUSE&lt;/td&gt;
         &lt;td&gt;10.3&lt;/td&gt;
         &lt;td&gt;2.2.4&lt;/td&gt;
         &lt;td&gt;5.0.45&lt;/td&gt;
         &lt;td&gt;5.2.4&lt;/td&gt;
    &lt;/tr&gt;
       &lt;tr&gt;
         &lt;td&gt;Fedora&lt;/td&gt;
         &lt;td&gt;8 Werewolf&lt;/td&gt;
         &lt;td&gt;2.2.6&lt;/td&gt;
         &lt;td&gt;5.0.45&lt;/td&gt;
         &lt;td&gt;5.2.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;Debian GNU/Linux&lt;/td&gt;
         &lt;td&gt;4.0 Etch&lt;/td&gt;
         &lt;td&gt;2.2.3&lt;/td&gt;
         &lt;td&gt;5.0.32
         &lt;/td&gt;&lt;td&gt;5.2.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;Mandriva Linux&lt;/td&gt;
         &lt;td&gt;2008.1&lt;/td&gt;
         &lt;td&gt;2.2.8&lt;/td&gt;
         &lt;td&gt;5.0.51a&lt;/td&gt;
         &lt;td&gt;5.2.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;Knoppix&lt;/td&gt;
         &lt;td&gt;5.3.1&lt;/td&gt;
         &lt;td&gt;2.2.8&lt;/td&gt;
         &lt;td&gt;5.0.51a&lt;/td&gt;
         &lt;td&gt;5.2.3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;Slackware Linux&lt;/td&gt;
         &lt;td&gt;12.0&lt;/td&gt;
         &lt;td&gt;2.2.4&lt;/td&gt;
         &lt;td&gt;5.0.37&lt;/td&gt;
         &lt;td&gt;5.2.3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
         &lt;td&gt;Gentoo Linux&lt;/td&gt;
         &lt;td&gt;2007.0&lt;/td&gt;
         &lt;td&gt;2.0.58&lt;/td&gt;
         &lt;td&gt;5.0.38&lt;/td&gt;
         &lt;td&gt;5.2.2&lt;/td&gt;
    &lt;/tr&gt;
   &lt;tr&gt;
         &lt;td&gt;FreeBSD&lt;/td&gt;
         &lt;td&gt;7.0 RELEASE&lt;/td&gt;
         &lt;td&gt;2.2.6&lt;/td&gt;
         &lt;td&gt;5.0.45&lt;/td&gt;
         &lt;td&gt;5.2.5&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;

</description>
    </item>
    
    <item>
      <title>Framework Popularity/Favouritism/Biase ...</title>
      <link>http://davedevelopment.co.uk/2008/04/28/framework-popularityfavouritismbiase.html</link>
      <pubDate>Mon, 28 Apr 2008 13:15:45 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/04/28/framework-popularityfavouritismbiase</guid>
      <description>&lt;p&gt;Started writing this post over a week ago, kind of lost interest, but I polished it off...&lt;/p&gt;


&lt;p&gt;After reading a &lt;a href=&quot;http://andyjeffries.co.uk/blog/why-i-think-ruby-on-rails-is-an-ideal-web-development-environment.html&quot;&gt;couple&lt;/a&gt; of &lt;a href=&quot;http://blog.hma-info.de/2008/04/16/response-to-andy-jeffries-why-ruby-is-better-than-symfony/&quot;&gt;posts&lt;/a&gt; this week arguing the corner of both &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; and &lt;a href=&quot;http://www.symfony-project.org/&quot;&gt;Symfony&lt;/a&gt;, I found myself thinking about which framework I like the most. I came to the conclusion that I don't really have a favourite, just the one I'm currently using. I've used the two previously mentioned frameworks, &lt;a href=&quot;http://www.cakephp.org/&quot;&gt;CakePHP&lt;/a&gt; a long time ago and more recently the &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt;. I like them all. They all do similar things, sometimes in different ways, but having spent a lot of time maintaining and developing 'frameworkless' sites, I think they're all mega. Admittedly, my PHP is far stronger than my Ruby, so I steer towards the PHP ones, but that has nothing to do with the frameworks themselves.&lt;/p&gt;


&lt;p&gt;Anyway, this lead me to have a little look on &lt;a href=&quot;http://www.google.com/trends&quot;&gt;Google Trends&lt;/a&gt;, to see how many people are searching for what on the framework front, I included the previously mentioned four and &lt;a href=&quot;http://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt;, which is very popular, but my Python is worse than my Ruby, so I've not used it. I know this is hardly conclusive, but it was worth a look.&lt;/p&gt;


&lt;p&gt;The results are pretty much what I expected. Django looks like it's a more common search term, but is starting to rise recently. Zend, CakePHP and Symfony are all slowly on the up, whereas Rails clearly had a big boom over the previous two years and is now settling down a bit.&lt;/p&gt;


&lt;p&gt;&lt;a href='http://davedevelopment.co.uk/wp-content/uploads/2008/04/screenshot2.png'&gt;&lt;img src=&quot;http://www.davedevelopment.co.uk/wp-content/uploads/2008/04/screenshot2-300x148.png&quot; alt=&quot;Google Trends for Frameworks&quot; title=&quot;Google Trends for Frameworks&quot; width=&quot;300&quot; height=&quot;148&quot; class=&quot;alignnone size-medium wp-image-57&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How To: Simple database migrations with Phing and DbDeploy</title>
      <link>http://davedevelopment.co.uk/2008/04/14/how-to-simple-database-migrations-with-phing-and-dbdeploy.html</link>
      <pubDate>Mon, 14 Apr 2008 09:20:08 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/04/14/how-to-simple-database-migrations-with-phing-and-dbdeploy</guid>
      <description>&lt;div class=&quot;alert-message block-message warning&quot;&gt;
    &lt;strong&gt;Update 02/11/2011&lt;/strong&gt;: I've since &lt;a href=&quot;/2011/11/01/phpmig-simple-migrations-for-php.html&quot;&gt;moved on&lt;/a&gt; from this method of running migrations, checkout &lt;a href=&quot;http://github.com/davedevelopment/phpmig&quot;&gt;phpmig on github&lt;/a&gt;.
&lt;/div&gt;




&lt;h4&gt;Introduction&lt;/h4&gt;


&lt;p&gt;This How To will introduce some simple database migrations to your PHP application. &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; is a popular &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_application_framework&quot;&gt;web application framework&lt;/a&gt;, that provides a method of migrating (upgrading) the applications database programatically, keeping the database schema essentially version controlled. This allows individual developers to update their working databases and the databases on testing, staging or production machines to be updated with new versions of applications. The &lt;a href=&quot;http://www.cakephp.org&quot;&gt;CakePHP&lt;/a&gt; framework has recently developed a &lt;a href=&quot;http://bakery.cakephp.org/articles/view/cake-db-migrations-v2-1&quot;&gt;migrations library&lt;/a&gt; simliar to rails, but this article focuses on using seperate tools to run database migrations, a build tool called &lt;a href=&quot;http://phing.info&quot;&gt;Phing&lt;/a&gt;, along with a method for creating database migrations, &lt;a href=&quot;http://dbdeploy.com/&quot;&gt;dbdeploy&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;Install Phing&lt;/h4&gt;


&lt;p&gt;I always use the beta or release candidate of phing and for the purposes of this article I suggest you do too. The best way to download and install phing is using &lt;a href=&quot;http://pear.php.net/&quot;&gt;PEAR&lt;/a&gt;. This can be done on Linux or Windows assuming you have the pear script in your PATH with three shell commands.&lt;/p&gt;




&lt;pre class=&quot;bash shell&quot;&gt;
shell&gt; pear channel-discover pear.phing.info
shell&gt; pear config-set preferred_state beta
shell&gt; pear install phing/phing
&lt;/pre&gt;




&lt;h4&gt;Example Application structure&lt;/h4&gt;


&lt;p&gt;As an example, we're going to develop a simple application with the following directory structure.&lt;/p&gt;


&lt;pre&gt;
example/
 |-- db/
 |   `-- deltas/
 |-- deploy/
 |   `-- scripts/  
 |-- library/
 `-- public/
&lt;/pre&gt;


&lt;p&gt;The &lt;tt&gt;db&lt;/tt&gt; directory contains sql files for using and manipulating our database and 
the &lt;tt&gt;deploy&lt;/tt&gt; directory contains our build scripts that set the migrations in motion. The library directory contains our application code and the &lt;tt&gt;public&lt;/tt&gt; folder will contain scripts and files accessible directly from the web, but will not be the focus of this article.&lt;/p&gt;




&lt;h4&gt;Build scripts&lt;/h4&gt;


&lt;p&gt;This section shows you how to develop the build scripts that will run the database migrations. The first file we need to create is a simple configuration file and should be fairly self explanatory. The file is written as &lt;tt&gt;key=value&lt;/tt&gt;, lines beginning with a &lt;tt&gt;#&lt;/tt&gt; are comments. Open your editor and save the following text as &lt;tt&gt;deploy/build.properties&lt;/tt&gt;.&lt;/p&gt;


&lt;pre&gt;
# Property files contain key/value pairs
#key=value

# This dir must contain the local application
build.dir=../

# Credentials for the database migrations
db.host=localhost
db.user=user
db.pass=password
db.name=example

# paths to programs
progs.mysql=/usr/bin/mysql
&lt;/pre&gt;




&lt;p&gt;The next file we are going to create is the &lt;tt&gt;deploy/build.xml&lt;/tt&gt; file. This is the file that tells Phing what we want it to do. I'm not going to go into too much detail describing each part of the build file, there are some comments, but you should consult the &lt;a href=&quot;http://phing.info/docs/guide/current/&quot;&gt;Phing Documentation&lt;/a&gt; for further details and enhancements.&lt;/p&gt;




&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;
&amp;lt;project name=&amp;quot;PurpleMonkey&amp;quot; basedir=&amp;quot;.&amp;quot; default=&amp;quot;build&amp;quot;&amp;gt;

    &amp;lt;!-- Sets the DSTAMP, TSTAMP and TODAY properties --&amp;gt;
    &amp;lt;tstamp/&amp;gt;

    &amp;lt;!-- Load our configuration --&amp;gt;
    &amp;lt;property file=&amp;quot;./build.properties&amp;quot; /&amp;gt;

    &amp;lt;!-- create our migration task --&amp;gt;
    &amp;lt;target name=&amp;quot;migrate&amp;quot; description=&amp;quot;Database Migrations&amp;quot;&amp;gt;  

        &amp;lt;!-- load the dbdeploy task --&amp;gt;
        &amp;lt;taskdef name=&amp;quot;dbdeploy&amp;quot; classname=&amp;quot;phing.tasks.ext.dbdeploy.DbDeployTask&amp;quot;/&amp;gt;

        &amp;lt;!-- these two filenames will contain the generated SQL to do the deploy and roll it back--&amp;gt;
        &amp;lt;property name=&amp;quot;build.dbdeploy.deployfile&amp;quot; value=&amp;quot;deploy/scripts/deploy-${DSTAMP}${TSTAMP}.sql&amp;quot; /&amp;gt;
        &amp;lt;property name=&amp;quot;build.dbdeploy.undofile&amp;quot; value=&amp;quot;deploy/scripts/undo-${DSTAMP}${TSTAMP}.sql&amp;quot; /&amp;gt;

        &amp;lt;!-- generate the deployment scripts --&amp;gt;
        &amp;lt;dbdeploy 
            url=&amp;quot;mysql:host=${db.host};dbname=${db.name}&amp;quot; 
            userid=&amp;quot;${db.user}&amp;quot; 
            password=&amp;quot;${db.pass}&amp;quot; 
            dir=&amp;quot;${build.dir}/db/deltas&amp;quot; 
            outputfile=&amp;quot;${build.dir}/${build.dbdeploy.deployfile}&amp;quot; 
            undooutputfile=&amp;quot;${build.dir}/${build.dbdeploy.undofile}&amp;quot; /&amp;gt;

        &amp;lt;!-- execute the SQL - Use mysql command line to avoid trouble with large files or many statements and PDO --&amp;gt;
        &amp;lt;exec
            command=&amp;quot;${progs.mysql} -h${db.host} -u${db.user} -p${db.pass} ${db.name} &amp;amp;lt; ${build.dbdeploy.deployfile}&amp;quot;
            dir=&amp;quot;${build.dir}&amp;quot;
            checkreturn=&amp;quot;true&amp;quot; /&amp;gt;
    &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;




&lt;p&gt;That's essentially all the magic we need. Now we just need to create our database.&lt;/p&gt;




&lt;h4&gt;Writing dbdeploy delta scripts&lt;/h4&gt;


&lt;p&gt;We haven't actually created our database, so rather than create it the traditional way, we will actually use the migrations to create the initial schema. We've not actually decided what our example application does yet, but seeing as most tutorials make blogs, why don't we give that a bash. We'll start simple, one table with three columns called &lt;tt&gt;post&lt;/tt&gt;.&lt;/p&gt;




&lt;table&gt;
    &lt;tr&gt;
        &lt;th&gt;Field&lt;/th&gt;
        &lt;th&gt;Type&lt;/th&gt;
        &lt;th&gt;Comment&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;title&lt;/td&gt;
        &lt;td&gt;VARCHAR(255)&lt;/td&gt;
        &lt;td&gt;The title of our post&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;time_created&lt;/td&gt;
        &lt;td&gt;DATETIME&lt;/td&gt;
        &lt;td&gt;The time we created our post&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;content&lt;/td&gt;
        &lt;td&gt;MEDIUMTEXT&lt;/td&gt;
        &lt;td&gt;The content of our post&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;




&lt;p&gt;Dbdeploy works by creating numbered delta files. Each delta files contains simple SQL to both deploy the change and roll it back. The basic layout of a delta file is like so.&lt;/p&gt;


&lt;pre name=&quot;code&quot; class=&quot;sql&quot;&gt;
--//

-- Run SQL to do the changes

--//@UNDO

-- RUN SQL to undo the changes

--//
&lt;/pre&gt;




&lt;p&gt;We are creating our initial schema, so put the following content in &lt;tt&gt;db/deltas/1-create_initial_schema.sql&lt;/tt&gt;&lt;/p&gt;




&lt;pre name=&quot;code&quot; class=&quot;sql&quot;&gt;
--//

CREATE TABLE `post` (
    `title` VARCHAR(255),
    `time_created` DATETIME,
    `content` MEDIUMTEXT
);

--//@UNDO

DROP TABLE `post`;

--//
&lt;/pre&gt;




&lt;h4&gt;Migrating the database&lt;/h4&gt;


&lt;p&gt;We are one step away from running our first migration. To keep track of the current version of the database, dbdeploy requires a table in the database. This is the only time we will have to interact with the mysql client directly.&lt;/p&gt;


&lt;pre class=&quot;shell bash&quot;&gt;
shell&gt; mysql -hlocalhost -uroot -ppassword example
mysql&gt; CREATE TABLE changelog (
  change_number BIGINT NOT NULL,
  delta_set VARCHAR(10) NOT NULL,
  start_dt TIMESTAMP NOT NULL,
  complete_dt TIMESTAMP NULL,
  applied_by VARCHAR(100) NOT NULL,
  description VARCHAR(500) NOT NULL
);
mysql&gt; ALTER TABLE changelog ADD CONSTRAINT Pkchangelog PRIMARY KEY (change_number, delta_set);                                                                                                                                                           
&lt;/pre&gt;




&lt;p&gt;We are now ready to run our first migration and create the initial schema for our application.&lt;/p&gt;




&lt;pre&gt;
shell&gt;cd deploy
shell&gt;phing migrate
&lt;/pre&gt;




&lt;p&gt;All being well, we now have a posts table in our database. But what about an author for our blog posts? We'll have to add another table and a foreign key from the post table to author table. To do this we create another delta, we call this one &lt;tt&gt;db/deltas/2-create_author_and_link_to_post.sql&lt;/tt&gt;

&lt;pre name=&quot;code&quot; class=&quot;sql&quot;&gt;
--//

CREATE TABLE `author` (
    `author_id` INT(10) unsigned auto_increment,
    `name` VARCHAR(255),
    PRIMARY KEY (`author_id`)
);

ALTER TABLE `post` ADD `author_id` INT(10) unsigned NULL;

--//@UNDO

ALTER TABLE `post` DROP `author_id`;

DROP TABLE `author`;

--//
&lt;/pre&gt;
&lt;/p&gt;


&lt;p&gt;Run our migrations again.&lt;/p&gt;


&lt;pre class=&quot;shell bash&quot;&gt;
shell&gt; cd deploy
shell&gt; phing migrate
&lt;/pre&gt;




&lt;h4&gt;Conclusion&lt;/h4&gt;


&lt;p&gt;That's pretty much it, you've seen how to create database deltas and use them to migrate your database, if you can't be bothered to copy and paste things to try for yourself, download the &lt;a href=&quot;/files/example_application.zip&quot;&gt;example application&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;There are plenty of caveats when it comes to version controlling databases, especially if you branch and merge your application code, some are &lt;a href=&quot;http://dbdeploy.com/documentation/getting-started/rules-for-using-dbdeploy/&quot;&gt;detailed&lt;/a&gt; in the dbdeploy documentation&lt;/p&gt;




&lt;p&gt;This tutorial is probably incomplete or wrong in plenty of ways, if you think you have something to point out, please leave your comments below&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Contributing to Open Source Software</title>
      <link>http://davedevelopment.co.uk/2008/04/03/contributing-to-open-source-software.html</link>
      <pubDate>Thu, 03 Apr 2008 16:09:56 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/04/03/contributing-to-open-source-software</guid>
      <description>&lt;p&gt;I'm a big fan of Open Source Software. Although I'm sure I could get by if I had to move to proprietary based software, at the present time, open source software earns me a living. Because of this, at the start of the year, I decided to give something back and start contributing to open source. I chose the &lt;a href=&quot;http://framework.zend.com&quot;&gt;Zend Framework&lt;/a&gt;, because it is written in PHP and is a project I have a lot of interest in. I registered for an account on the &lt;a href=&quot;http://framework.zend.com/issues/&quot;&gt;bug tracker&lt;/a&gt; and signed the &lt;a href=&quot;http://framework.zend.com/wiki/display/ZFPROP/Contributor+License+Agreement&quot;&gt;CLA&lt;/a&gt;, but that's as far as I got. I started looking through some of the bugs available for fixing, but found that the simpler ones were being dealt with quickly by other people and the only ones left where a little too complex for me. I still plan to contribute before the year is over. I intend to use the framework for a project I have in mind and the frameworks current implementation of a client for &lt;a href=&quot;http://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt; needs adding to for the purposes I need, so maybe I can contribute that way.&lt;/p&gt;

&lt;p&gt;Back to the point, today I think I found a bug in &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt;, I couldn't work out how to submit a bug report via the website, so I emailed &lt;a href=&quot;http://sebastian-bergmann.de/&quot;&gt;Sebastian Bergmann&lt;/a&gt; with a patch. I'm not going to describe the bug until I know for sure that I'm correct, but I'm at least 90% sure I'm in the right. So, if I am right, that's my first solid contribution to open source software.&lt;/p&gt;

&lt;h5&gt;Update&lt;/h5&gt;


&lt;p&gt;Well it seems I was right in reporting the bug, but it appears Sebastian didn't like the patch I sent, or more likely it didn't work. This &lt;a href=&quot;http://www.phpunit.de/changeset/2708&quot;&gt;changeset&lt;/a&gt; looks slightly different to the patch I submitted.

&lt;pre class=&quot;patch&quot;&gt;
Index: PHPUnit/Util/Metrics/Function.php
===================================================================
--- PHPUnit/Util/Metrics/Function.php   (revision 2707)
+++ PHPUnit/Util/Metrics/Function.php   (working copy)
@@ -449,7 +449,7 @@
         }

         else {
-            $this-&gt;crap = pow($this-&gt;ccn, 2) * (pow(1 - $this-&gt;coverage/100, 3) + $this-&gt;ccn);
+            $this-&gt;crap = pow($this-&gt;ccn, 2) * pow(1 - $this-&gt;coverage/100, 3) + $this-&gt;ccn;
         }
     }

&lt;/pre&gt;

&lt;/p&gt;


&lt;p&gt;From what I can tell, the change put into place is also incorrect according to the &lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=210575&quot;&gt;C.R.A.P. index&lt;/a&gt; formula.&lt;/p&gt;




&lt;h5&gt;Update 2&lt;/h5&gt;




&lt;p&gt;I emailed Sebastian and he fixed it properly in &lt;a href=&quot;http://www.phpunit.de/changeset/2712&quot;&gt;changeset 2712&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Linux/PHP one liner - Syntax check all files.</title>
      <link>http://davedevelopment.co.uk/2008/03/25/linuxphp-one-liner-syntax-check-all-files.html</link>
      <pubDate>Tue, 25 Mar 2008 17:41:21 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/03/25/linuxphp-one-liner-syntax-check-all-files</guid>
      <description>&lt;p&gt;Here's a simple one liner you can use to syntax check all php files in your working directory.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;find . -type f -name &quot;*.php&quot; -exec php -l {} \; | grep -v 'No syntax errors'&lt;/pre&gt;


&lt;p&gt;For those not familiar with the programs used, it basically reads as.... Find all files that end in '.php' and with each of those files run &lt;tt&gt;php -l&lt;/tt&gt;. This is then put through a pipe to the &lt;tt&gt;grep -v&lt;/tt&gt;, which filters out all files that are syntactically correct.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sifr turned off</title>
      <link>http://davedevelopment.co.uk/2008/03/20/sifr-turned-off.html</link>
      <pubDate>Thu, 20 Mar 2008 19:24:09 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/03/20/sifr-turned-off</guid>
      <description>&lt;p&gt;I noticed some problems with my browser (FF2/Ubuntu) with the Sifr headings on the posts, so I've commented them out, sorry about the horrible blue heading links ;)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>10 tools for Modern PHP Development</title>
      <link>http://davedevelopment.co.uk/2008/03/20/10-tools-for-modern-php-development.html</link>
      <pubDate>Thu, 20 Mar 2008 19:16:35 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2008/03/20/10-tools-for-modern-php-development</guid>
      <description>&lt;p&gt;A simple list of tools for modern PHP development. There are alternatives to most of the tools, but I'll list native PHP tools wherever possible.&lt;/p&gt;

&lt;h4&gt;1. &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;PHPUnit is a testing framework belonging to the xUnit family of testing frameworks. Use it to write and run automated tests. &lt;a href=&quot;http://www.phpunit.de/pocket_guide/3.2/en/index.html&quot;&gt;Start using PHPUnit&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;2. &lt;a href=&quot;http://selenium-rc.openqa.org/&quot;&gt;Selenium RC&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Selenium RC can be used in conjunction with PHPUnit to create and run automated tests within a web browser. It allows tests to be run on several modern browsers and is implemented in Java, making it available to different platforms. &lt;a href=&quot;http://www.phpunit.de/pocket_guide/3.1/en/selenium.html&quot;&gt;PHPUnit and Selenium&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;3. &lt;a href=&quot;http://pear.php.net/PHP_CodeSniffer&quot;&gt;PHP CodeSniffer&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;PHP CodeSniffer is a PHP code tokenizer, that will analyse your code and report errors and warnings based on a set of Coding Standards. &lt;a href=&quot;http://pear.php.net/manual/en/package.php.php-codesniffer.php&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;4. &lt;a href=&quot;http://phing.info/trac/&quot;&gt;Phing&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Phing is a project build tool and is a PHP port of the popular Java program &lt;a href=&quot;http://ant.apache.org/&quot;&gt;ant&lt;/a&gt;. Phing can be used to automate builds, database migration, deployment and configuration of code. &lt;a href=&quot;http://phing.info/docs/guide/current/&quot;&gt;Documentation&lt;/a&gt;. &lt;a href=&quot;http://davedevelopment.co.uk/2008/04/14/how-to-simple-database-migrations-with-phing-and-dbdeploy/&quot; title=&quot;Database migrations with phing&quot;&gt;Database migrations with phing&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;5. &lt;a href=&quot;http://xdebug.org/&quot;&gt;Xdebug&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Xdebug is a multi-purpose tool, providing remote debugging, stack traces, function traces, profiling and code coverage analysis. Debug clients are available in many &lt;a href=&quot;http://www-128.ibm.com/developerworks/library/os-php-ide/index.html&quot;&gt;PHP IDE&lt;/a&gt;s and even &lt;a href=&quot;http://tech.blog.box.net/2007/06/20/how-to-debug-php-with-vim-and-xdebug-on-linux/&quot;&gt;plugins&lt;/a&gt; so you can debug from everybody's favourite editor &lt;a href=&quot;http://vim.org&quot;&gt;vim&lt;/a&gt;. &lt;a href=&quot;http://xdebug.org/docs/&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;6. &lt;a href=&quot;http://www.phpdoc.org/&quot;&gt;PHPDocumentor&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;PHPDocumentor is an automated documentation tool, that allows you to write specifically formatted comments in your code, that can be brought together to created API documentation. &lt;a href=&quot;http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.pkg.html&quot;&gt;Tutorial&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;7. &lt;a href=&quot;http://www.phpunit.de/wiki/phpUnderControl&quot;&gt;phpUnderControl&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;phpUnderControl is a patch for the popular &lt;a href=&quot;http://martinfowler.com/articles/continuousIntegration.html&quot;&gt;Continuous Integration&lt;/a&gt; tool, &lt;a href=&quot;http://cruisecontrol.sourceforge.net/&quot;&gt;CruiseControl&lt;/a&gt;. Together with the previous six tools, phpUnderControl gives you a great overview of the current state of your application/codebase. Keep an eye out for &lt;a href=&quot;http://sourceforge.net/projects/xinc&quot;&gt;Xinc&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;8. &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; - or &amp;lt;insert your favourite framework here&amp;gt;&lt;/h4&gt;


&lt;p&gt;Frameworks facilitate the development of software, by allowing developers to focus on the business requirements of the software, rather than the repetitive and tedious elements of development, such as caching. There are plenty of frameworks to choose from, but I particularly like the Zend Framework. Have a read through this excellent &lt;a href=&quot;http://akrabat.com/zend-framework-tutorial/&quot;&gt;Getting started guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;9. &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Subversion is a revision control system that has superceded &lt;a href=&quot;http://www.nongnu.org/cvs/&quot;&gt;CVS&lt;/a&gt;. If you're writing software of any kind, you shoud be using version control software.&lt;a href=&quot;http://svnbook.red-bean.com/&quot;&gt;SVN Book&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;10. &lt;a href=&quot;http://www.atlassian.com/software/jira/&quot;&gt;Jira&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;So I could have named one of many, but this is the one I've liked the most recently. Jira is a bug/issue tracking software package and can also help with project management in terms of goals and roadmaps. Most issue trackers link to version control repositories, such as Subversion. Only downside to Jira is that it costs for non open source projects.&lt;/p&gt;

&lt;p&gt;I'm pleased to say that with a little bit of pushing and persuasion by myself, we are currently using all of these technologies with the exception of Jira, we have a bespoke issue tracker.&lt;/p&gt;

&lt;p&gt;What do you think to the list? Anything I have missed? Any alternatives you prefer?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New site - LimoTrack.co.uk</title>
      <link>http://davedevelopment.co.uk/2007/09/23/new-site-limotrackcouk.html</link>
      <pubDate>Sun, 23 Sep 2007 04:06:18 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/09/23/new-site-limotrackcouk</guid>
      <description>&lt;p&gt;Kind of pre-launched a site for a friend this week, he's started a new business with a slight twist of a limosine service, he's going to be ferrying people around in a fully-tracked articulated vehicle, which is kind of like a tank people carrier. Will post later with a press release and a few technical tidbits on the site.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.limotrack.co.uk&quot; title=&quot;Tank for hire&quot;&gt;Hardman LimoTrack&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Capistrano, Migrations and Which-Broadband updates</title>
      <link>http://davedevelopment.co.uk/2007/09/11/capistrano-migrations-and-which-broadband-updates.html</link>
      <pubDate>Tue, 11 Sep 2007 00:07:43 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/09/11/capistrano-migrations-and-which-broadband-updates</guid>
      <description>&lt;p&gt;I've been sitting on some code updates for www.which-broadband.net for a while now, what seems like ages ago I added a simple news section and adding link redirecting along with click tracking, but didn't get around to releasing it. I actually made a couple of sales of the site the last couple of months, so I thought I'd make a little effort to tidy things up, but decided to do it the long winded way and learn something in the process. I've read lots about &lt;a href=&quot;http://manuals.rubyonrails.com/read/book/17&quot;&gt;Capistrano&lt;/a&gt; before, but never really put it into practice, now seemed like the time and also to try the &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Migration.html&quot;&gt;ActiveRecord's migrations&lt;/a&gt;. Most of it went swimmingly, the biggest annoyance I found was ActiveRecords MySQL implementation, in that the BIGINT's I had were only integers to ActiveRecord so once I created the database with migrations, the columns wouldn't hold a number large enough. I got round this by making the columns strings and overiding the accessor and modifier in the model in question and then things were fine. I also had problems where I was reading the Capistrano one manual, but using version 2, which has some major differences. Anyway now I have an updated version of my site online, plus an automated deployment tool readily available, lets hope I'll make more frequent updates. I'm doing a few little tests with &lt;a href=&quot;http://adwords.google.com&quot;&gt;AdWords&lt;/a&gt; to see if I can do any click-flipping, if nothing works I'll just leave it alone for now, don't have the time to push it too hard.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Getting things done</title>
      <link>http://davedevelopment.co.uk/2007/07/10/getting-things-done.html</link>
      <pubDate>Tue, 10 Jul 2007 09:21:51 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/07/10/getting-things-done</guid>
      <description>&lt;p&gt;Been a long time since I've posted, taken a step back from freelance work as of late and I've been doing lots of other things. One of them is reading David Allen's &lt;a href=&quot;http://www.amazon.co.uk/gp/product/0749922648?ie=UTF8&amp;tag=davedvd-21&amp;linkCode=as2&amp;camp=1634&amp;creative=6738&amp;creativeASIN=0749922648&quot;&gt;Getting Things Done&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.co.uk/e/ir?t=davedvd-21&amp;l=as2&amp;o=2&amp;a=0749922648&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;. Thus far I've found it pretty interesting and just knowing that I should organise myself better has lead to some improvements. I've started using some software to keep track of things, it's a Ruby on Rails application based on the principles of &lt;em&gt;Getting Things Done&lt;/em&gt;, I just run it locally using webrick and it's quite nice, definitely worth a &lt;a href=&quot;http://www.rousette.org.uk/projects/&quot; title=&quot;Tracks - Getting Things Done&quot;&gt;look&lt;/a&gt;.&lt;/p&gt;

&lt;iframe src=&quot;http://rcm-uk.amazon.co.uk/e/cm?t=davedvd-21&amp;o=2&amp;p=8&amp;l=as1&amp;asins=0749922648&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;

</description>
    </item>
    
    <item>
      <title>How To: Send SQL commands to a database in VIM</title>
      <link>http://davedevelopment.co.uk/2007/03/29/how-to-send-sql-commands-to-a-database-in-vim.html</link>
      <pubDate>Thu, 29 Mar 2007 09:02:30 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/03/29/how-to-send-sql-commands-to-a-database-in-vim</guid>
      <description>&lt;p&gt;A simple way of sending SQL to your database from everyone's favourite editor &lt;a href=&quot;http://www.vim.org&quot; title=&quot;Vim - The Editor&quot;&gt;Vim&lt;/a&gt;, without any plugins or macros.&lt;/p&gt;

&lt;p&gt;Firstly we need to add a custom command to our &lt;tt&gt;.vimrc&lt;/tt&gt;, open it up and add the following line, where:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;tt&gt;CommandName&lt;/tt&gt; - The name of your command&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;Username&lt;/tt&gt; - The username for this database&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;Password&lt;/tt&gt; - The password for this database&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;Database&lt;/tt&gt; - The name of the database&lt;/li&gt;
&lt;/ul&gt;




&lt;pre class=&quot;code&quot;&gt;
:command -range=% CommandName :&amp;lt;line1&amp;gt;,&amp;lt;line2&amp;gt;w !mysql -uUsername -pPassword Database -t 
&lt;/pre&gt;


&lt;p&gt;For example:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
:command -range=% SendDB :&amp;lt;line1&amp;gt;,&amp;lt;line2&amp;gt;w !mysql -utest -ptest test -t 
&lt;/pre&gt;


&lt;p&gt;That's all the setting up we need. As you can see, after the exclamation mark is just the regular &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/mysql.html&quot;&gt;MySQL Command line tool&lt;/a&gt; and various options.&lt;/p&gt;

&lt;p&gt;Fire up &lt;a href=&quot;http://www.vim.org&quot; title=&quot;Vim - The Editor&quot;&gt;vim&lt;/a&gt; and start editing your sql.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
# vim test.sql
&lt;/pre&gt;


&lt;p&gt;As an example, here's some simple SQL.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
-- Drop existing table
DROP TABLE IF EXISTS `test`;

-- Create table
CREATE TABLE IF NOT EXISTS `test` (
    `test_id` INT(11) NOT NULL auto_increment,
    `name` VARCHAR(255) NOT NULL,
    PRIMARY KEY (`test_id`)
);

-- Add our data
INSERT INTO `test`(`name`) VALUES('dave');

-- Get it back out again
SELECT * FROM `test`;
&lt;/pre&gt;


&lt;p&gt;If we're happy with what we've written, while in command mode, type &lt;tt&gt;:SendDB&lt;/tt&gt;, or whatever you called your command and hit enter. If it works, you'll see something like this.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
~/test.sql[+][sql] unix 
:SendDB
+---------+------+
| test_id | name |
+---------+------+
|       1 | dave | 
+---------+------+

Press ENTER or type command to continue
&lt;/pre&gt;


&lt;p&gt;You can always add to the custom command, in particular piping the output to less can be effective for larger result sets.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Related Searches, Web Pages and Videos on Adsense</title>
      <link>http://davedevelopment.co.uk/2007/02/23/related-searches-web-pages-and-videos-on-adsense.html</link>
      <pubDate>Fri, 23 Feb 2007 07:05:47 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/02/23/related-searches-web-pages-and-videos-on-adsense</guid>
      <description>&lt;p&gt;I've just seen the following &lt;a href=&quot;http://adsense.google.com&quot;&gt;Adsense&lt;/a&gt; block on the &lt;a href=&quot;http://www.ubuntuforums.org/&quot;&gt;Ubuntu Forums&lt;/a&gt;, not seen one before. Click the thumb to see the full size image.
&lt;a href=&quot;/files/related.png&quot; title=&quot;Related Searches, Web Pages and Videos on Adsense&quot;&gt;&lt;img src=&quot;/files/related_300.png&quot; alt=&quot;Related Searches, Web Pages and Videos on Adsense&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Get paid to search the web with SlashMySearch</title>
      <link>http://davedevelopment.co.uk/2007/02/16/get-paid-to-search-the-web-with-slashmysearch.html</link>
      <pubDate>Fri, 16 Feb 2007 09:33:01 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/02/16/get-paid-to-search-the-web-with-slashmysearch</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.slashmysearch.com/earn/id/3554&quot;&gt;SlashMySearch&lt;/a&gt; is a internet search engine that pays it uses as they search. An interesting thought, I'm sure there are plenty of sites like this out there, but I thought I'd give it a try. I came across it at &lt;a href=&quot;http://www.cjcm2u.com/2007/02/13/earn-extra-money-doing-what-you-do-everyday-using-a-search-engine/&quot;&gt;CJCM and IT&lt;/a&gt; via &lt;a href=&quot;http://www.problogger.net/archives/2007/02/17/speedlinking-reader-edition-17-february-2007/&quot;&gt;ProBlogger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Simply &lt;a href=&quot;http://www.slashmysearch.com/earn/signup.html?id=3554&quot;&gt;signup&lt;/a&gt; and set your unique URL as your homepage. I don't think it's everybodies cup of tea and it might get a little annoying but it's got to be worth a try. They also run a referral program, so tell your friends!.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DaveWP Wordpress Theme</title>
      <link>http://davedevelopment.co.uk/2007/02/06/davewp_wordpress_theme.html</link>
      <pubDate>Tue, 06 Feb 2007 18:26:33 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/02/06/davewp_wordpress_theme</guid>
      <description>&lt;p&gt;&lt;img src=&quot;/files/screenshot_thumb.jpg&quot; alt=&quot;DaveWP screenshot&quot; style=&quot;float:left; margin:0px 5px 5px 0px&quot; /&gt;I figure it's about time I updated my blog and designed a new theme, but before I do I thought I would tidy this one up and release it. just like I told 'Big John' from &lt;a href=&quot;http://www.positioniseverything.net&quot;&gt;Position is Everything&lt;/a&gt; I would do well over a year ago. It's far from perfect, but I kind of like it and it made a good project for me to experiment with some new design technologies.&lt;/p&gt;

&lt;p&gt;The layout is based on the &lt;a href=&quot;http://www.positioniseverything.net/articles/jello.html&quot;&gt;The Jello Mold Piefecta Layout&lt;/a&gt;, being a 3 column, source ordered, fixed width, equal height column layout. The template also uses &lt;a href=&quot;http://www.mikeindustries.com/sifr/&quot;&gt;sIfr&lt;/a&gt; ( to produce rich and accessable headings.&lt;/p&gt;

&lt;p&gt;Looking back I was clearly influenced by &lt;a href=&quot;http://www.mikeindustries.com/blog/&quot;&gt;Mike Davidsons Blog&lt;/a&gt; design, for which I apologise to him and in no way take credit for the 'look' of the theme.&lt;/p&gt;

&lt;p&gt;Get the &lt;a href=&quot;/files/davewp-1.0.zip&quot; title=&quot;Download DaveWP 1.0 Zip File&quot;&gt;zip&lt;/a&gt; or &lt;a href=&quot;/files/davewp-1.0.tar.gz&quot; title=&quot;Download DaveWP 1.0 Gzipped Tarball&quot;&gt;gzipped tarball&lt;/a&gt;. Feedback and comments would be appreciated, but not quite as much as bug reports and fixes.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>PHP Conference London 2007</title>
      <link>http://davedevelopment.co.uk/2007/01/23/php-conference-london-2007.html</link>
      <pubDate>Tue, 23 Jan 2007 06:36:03 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/01/23/php-conference-london-2007</guid>
      <description>&lt;p&gt;A couple of days behind with this one, but I thought I'd post to help out. As alot of the PHP community have mentioned, The PHP London user group are running the &lt;a href=&quot;http://www.phpconference.co.uk/&quot;&gt;UK's second dedicated PHP conference&lt;/a&gt; on Friday, 23rd February. Confirmed speakers thus far are, Cal Evans, Simon Laws,  Kevlin Henney and Rasmus Lerdorf.&lt;/p&gt;

&lt;p&gt;I didn't make it last year but will see what I can sort out this year.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Joined Elance.com</title>
      <link>http://davedevelopment.co.uk/2007/01/22/joined-elancecom.html</link>
      <pubDate>Mon, 22 Jan 2007 16:23:46 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2007/01/22/joined-elancecom</guid>
      <description>&lt;p&gt;After reading this &lt;a href=http://www.elance.com/p/corporate/community/resource-center/elancer-oct-06.html&quot;&gt;news article&lt;/a&gt;, (funnily enough through my &lt;acronym title=&quot;Really Simple Syndication&quot;&gt;RSS&lt;/acronym&gt; feed of &lt;a href=&quot;http://www.digg.com&quot; title=&quot;digg.com&quot;&gt;digg.com&lt;/a&gt;'s programming section) I decided to sign up for a month to see what &lt;a href=&quot;http://www.elance.com?rid=13IG9&quot;&gt;Elance.com&lt;/a&gt; was like.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.elance.com/postjob?rid=13IG9&quot;&gt;&lt;img border=0 src='http://images.elance.com/images/webdev-2.gif'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically Elance is a community to bring together people who want to do work and people need work doing. People or companies post projects in the various categories and then service providers must make proposals, the most impressive being likely to get the contract. Posting projects is free and the charges are made to the people providing the work at a rate of 8.75%.&lt;/p&gt;

&lt;p&gt;This seems quite costly for the freelancers, expecially seeing as you have to pay to subscribe as well, but as a trial I'll try and complete projects at cost and not make a profit.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Desktop switch to Ubuntu</title>
      <link>http://davedevelopment.co.uk/2006/12/19/desktop-switch-to-ubuntu.html</link>
      <pubDate>Tue, 19 Dec 2006 18:19:06 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/12/19/desktop-switch-to-ubuntu</guid>
      <description>&lt;p&gt;Just a quick note, I've recently moved from &lt;a href=&quot;http://www.gentoo.org&quot; title=&quot;Gentoo Linux&quot;&gt;Gentoo&lt;/a&gt; to &lt;a href=&quot;http://www.ubuntu.org&quot; title=&quot;Ubuntu Linux&quot;&gt;Ubuntu&lt;/a&gt; on my desktop machine at home. I had a few problems with my Gentoo install and while I find Gentoo great for learning the ins and outs of things, as I do more and more freelance work, I need a OS environment that's not going to let me down. My point being environment, Gentoo is more than capable of being extremely stable, but it takes a lot more knowledge to get it and keep it stable. Whilst I was happy learning and taking my time before, things need to happen a little more urgently now.&lt;/p&gt;

&lt;p&gt;I chose Ubuntu mainly because I run &lt;a href=&quot;http://www.debian.org&quot; title=&quot;Debian GNU Linux&quot;&gt;Debian&lt;/a&gt; on my dedicated servers and am already familiar with the package management, but also because I wanted to see what the fuss is a bout. I'm very pleased so far. I'm running &lt;a href=&quot;http://www.getfirefox.com&quot; title=&quot;Mozilla Firefox&quot;&gt;Mozilla Firefox&lt;/a&gt;, &lt;a href=&quot;http://www.mozilla.com/en-US/thunderbird/&quot; title=&quot;Mozilla Thunderbird&quot;&gt;Mozilla Thunderbird&lt;/a&gt;, &lt;a href=&quot;http://www.gnucash.org/&quot; title=&quot;GNUCash&quot;&gt;GNUCash&lt;/a&gt;, &lt;a href=&quot;http://www.openoffice.org&quot; title=&quot;OpenOffice.org&quot;&gt;OpenOffice.org&lt;/a&gt;, &lt;a href=&quot;http://amarok.kde.org/&quot; title=&quot;Amarok&quot;&gt;Amarok&lt;/a&gt; and &lt;a href=&quot;http://ktorrent.org/&quot; title=&quot;KTorrent&quot;&gt;KTorrent&lt;/a&gt; day to day, the latter two despite using &lt;a href=&quot;http://www.gnome.org/&quot; title=&quot;GNOME&quot;&gt;GNOME&lt;/a&gt; for my desktop.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Projects in the pipeline</title>
      <link>http://davedevelopment.co.uk/2006/12/08/projects-in-the-pipeline.html</link>
      <pubDate>Fri, 08 Dec 2006 11:46:09 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/12/08/projects-in-the-pipeline</guid>
      <description>&lt;p&gt;I have a few projects that are in the pipeline, some are at the design stage, some are just notes written in my 'ideas' pad, thought I'd share a few.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.ingletonplumbingandheating.co.uk&quot; title=&quot;Ingleton Plumbing and Heating&quot;&gt;Ingleton Plumbing and Heating&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;This is a project I started about 4 years ago for a friend, at one stage I got a fairly decent design done and was just waiting on a bit of content, but that got lost along with the design for the &lt;a href=&quot;http://www.atstsolutions.co.uk&quot; title=&quot;ATST Solutions&quot;&gt;ATST Solutions&lt;/a&gt; site after a hard drive failure and a lack of backup. I've got a very basic design going, needs some flair.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.phpbookreviews.com&quot; title=&quot;PHP Book Reviews&quot;&gt;PHP Book Reviews&lt;/a&gt; and &lt;a href=&quot;http://www.starwarsbookreviews.com&quot; title=&quot;Star Wars Book Reviews&quot;&gt;Star Wars Book Reviews&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;I decided to start these two as little niche book review sites. I read a lot of &lt;a href=&quot;http://www.starwars.com&quot;&gt;Star Wars&lt;/a&gt; books and a few &lt;a href=&quot;http://www.php.net&quot;&gt;PHP&lt;/a&gt; books and figured I could write my own reviews, use amazon's web services to get other peoples views and attempt to make money through the affiliate links. I decided to do this seeing as one of the most popular posts on this blog is the &lt;a href=&quot;http://davedevelopment.co.uk/2006/01/22/book-review-essential-php-security/&quot; title=&quot;Book Review: Essential PHP Security&quot;&gt;Essential PHP Security Book Review&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;A price comparison site&lt;/h4&gt;


&lt;p&gt;I have a few ideas aimed around creating a price comparison site, starting small but hopefully getting big. I plan on using product feeds from the various affiliate networks and have a rather cunning marketing plan, not one that hasn't been done before, but I don't think anybody has done it in this area before. I've got a couple of thoughts on the name, one of which is treading a little too closely on PriceRunner, but I'm in no rush with this one.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Google taking over day to day tasks...</title>
      <link>http://davedevelopment.co.uk/2006/12/07/google-taking-over-day-to-day-tasks.html</link>
      <pubDate>Thu, 07 Dec 2006 18:21:30 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/12/07/google-taking-over-day-to-day-tasks</guid>
      <description>&lt;p&gt;I'm sorry to say it but I've started to cave in and use &lt;a href=&quot;http://www.google.com&quot;&gt;Google's&lt;/a&gt; range of web applications to deal with day to day tasks. It all started when I finally made myself start using a calendar and I figured &lt;a href=&quot;http://www.google.com/calendar&quot; title=&quot;Google Calendar&quot;&gt;Google Calendar&lt;/a&gt; would be the best place to start. Since then I've started using the &lt;a href=&quot;http://www.google.com/alerts&quot; title=&quot;Google Alerts&quot;&gt;Alerts&lt;/a&gt; service, sending emails to the &lt;a href=&quot;http://gmail.google.com/&quot; title=&quot;Google Mail&quot;&gt;GMail&lt;/a&gt; account I've had for ages but never used and now I've even switched from &lt;a href=&quot;http://www.bloglines.com&quot; title=&quot;Bloglines&quot;&gt;Bloglines&lt;/a&gt; to &lt;a href=&quot;http://www.google.com/reader&quot; title=&quot;Google Reader&quot;&gt;Google Reader&lt;/a&gt;. I've also been using &lt;a href=&quot;http://www.google.com/analytics/&quot; title=&quot;Google Analytics&quot;&gt;Google Analytics&lt;/a&gt; to track statistics on the &lt;a href=&quot;http://www.daveproxy.co.uk&quot; title=&quot;DaveProxy - free web proxy&quot;&gt;DaveProxy&lt;/a&gt; site.&lt;/p&gt;

&lt;p&gt;The following is a little review of each application, what I like and what I don't.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.google.com/calendar&quot; title=&quot;Google Calendar&quot;&gt;Google Calendar&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Google Calendar is a shared calendar application, allowing users to manage their personal calendar and publish parts they would like to, to colleagues and friends. There are also other shared calendars, for example I have &lt;a href=&quot;http://www.barnsleyfc.co.uk&quot;&gt;Barnsley's&lt;/a&gt; fixtures showing in my calendar. I've no complaints to make about the calendar application, it's nice and easy to use and it sends me SMS reminders, all free of charge.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.google.com/alerts&quot; title=&quot;Google Alerts&quot;&gt;Google Alerts&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Whilst I haven't used the Alerts service all that much, I think it's an awesome tool. It's extremely easy tool to use, I was quite suprised to see my Boss using it, receiving alerts based on our company name. Basically you register keywords with the alerts service and tell it how often you want emailing. If any new pages turn up in the google index within that timeframe, you'll receive an email with a link to that page. Simple.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://gmail.google.com/&quot; title=&quot;Google Mail&quot;&gt;GMail&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;Again, I've not used gmail too much, right now I only receive my google alerts to my gmail address, but as far as webmail goes it's pretty good. I'd definitely like to see the ability to drag and drop like a &lt;a href=&quot;http://www.roundcube.net/&quot;&gt;RoundCube&lt;/a&gt; installation can, but otherwise it's more than what I need.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.google.com/reader&quot; title=&quot;Google Reader&quot;&gt;Google Reader&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;I've been using Google Reader to read and manage all my RSS feeds for about a week now after switching over from &lt;a href=&quot;http://www.bloglines.com&quot; title=&quot;Bloglines&quot;&gt;Bloglines&lt;/a&gt; and I have mixed feelings. Importing my feeds was easy enough, thanks partially to Bloglines being nice enough to allow me to export them. Google reader by default marks feed entries as read when you scroll past them, which seems pretty cool but two things annoy me. The first is probably a browser issue, but whenever an entry is marked as read, the number in brackets next to the feed or category link on the left changes, as it should, but this causes some of my category links to span two lines, then one line, then two lines again. It's basically a little flicker on the left hand side of the screen which is a little distracting. The second thing is, if there's only one entry in a feed or category that is less than the windows height in length, I don't scroll, so it doesn't get marked as read. Other than that, it could do with being a little faster, but I'm sure it'll be constantly improving on that front.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.google.com/analytics/&quot; title=&quot;Google Analytics&quot;&gt;Google Analytics&lt;/a&gt;&lt;/h4&gt;


&lt;p&gt;I'm very impressed with the analytics service, it makes it very easy for me to monitor the proxy website, which &lt;a href=&quot;http://www.awstats.com&quot;&gt;AWStats&lt;/a&gt; isn't really appropriate, definitely worth checking out.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New Site Launched: Pontiac Trans Am UK</title>
      <link>http://davedevelopment.co.uk/2006/11/21/new-site-launched-pontiac-trans-am-uk.html</link>
      <pubDate>Tue, 21 Nov 2006 16:54:30 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/11/21/new-site-launched-pontiac-trans-am-uk</guid>
      <description>&lt;p&gt;This past weekend I acquired myself a new baby and decided to put a site up about it. It's all very basic and rushed, running off Wordpress and ZenPhoto, but cool all the same.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.pontiactransam.co.uk&quot; title=&quot;Pontiac Trans Am UK&quot;&gt;PTAUK&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Quick Tip: Cygwin here shortcut, Explorer here shortcut</title>
      <link>http://davedevelopment.co.uk/2006/10/19/quick-tip-cygwin-here-shortcut-explorer-here-shortcut-2.html</link>
      <pubDate>Thu, 19 Oct 2006 04:53:50 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/10/19/quick-tip-cygwin-here-shortcut-explorer-here-shortcut-2</guid>
      <description>&lt;p&gt;Thanks to &lt;a href=&quot;http://www.cygwin.com/ml/cygwin/2004-06/msg00201.html&quot;&gt;this mailing list post&lt;/a&gt; I now have a 'Bash here' option in my windows explorer context menu for folders and drives. Simply add &lt;a href=&quot;/files/scripts/bash_here.reg&quot;&gt;this registry script&lt;/a&gt; to the windows registry.&lt;br /&gt;&lt;br /&gt;Thanks to my self and this little script, I can open a 'windows explorer window here' from within cygwin.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;#! /bin/bash
PWD=&lt;code&gt;pwd&lt;/code&gt;
PATH=&lt;code&gt;cygpath -w $PWD&lt;/code&gt;
/cygdrive/c/WINDOWS/explorer.exe $PATH
&lt;/pre&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New site launched for AJW ltd.</title>
      <link>http://davedevelopment.co.uk/2006/10/18/new-site-launched-for-ajw-ltd.html</link>
      <pubDate>Wed, 18 Oct 2006 06:11:49 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/10/18/new-site-launched-for-ajw-ltd</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.ajwltd.co.uk&quot; title=&quot;AJW - Quality Bespoke Joiner&quot;&gt;&lt;img style=&quot;float:left; margin-right:5px;&quot; src=&quot;/files/ajw_thumb.png&quot; alt=&quot;AJW Website&quot; /&gt;&lt;/a&gt;I launched a new site today, assuming the updated DNS records are rippling around the world as I type. The site was done as a favour to a friend, is very basic but I think it gets the point across.&lt;/p&gt;

&lt;p&gt;The company are a bespoke joinery specialist, particularly architectural joinery and trade as &lt;a href=&quot;http://www.ajwltd.co.uk&quot; title=&quot;AJW - Quality Bespoke Joiner&quot;&gt;Architectural Joinery Workshops Ltd. (AJW)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still a few things to do to the site, but I'll get those done shortly. Namely, some sort of templating system to ease updates and modifications, meta tags and then a little bit of marketing to see if we can develop some decent rankings.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Congratulations to the BareNakedApp guys</title>
      <link>http://davedevelopment.co.uk/2006/09/07/congratulations-to-the-barenakedapp-guys.html</link>
      <pubDate>Thu, 07 Sep 2006 03:57:49 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/09/07/congratulations-to-the-barenakedapp-guys</guid>
      <description>&lt;p&gt;I just wanted to say congratulations to Ryan and his team and to thank them for running the blog, it's been quite inspirational and extremely informative for me. One day, once I come up with the right idea, I might follow in their footsteps.&lt;/p&gt;

&lt;p&gt;If you didn't know, for a while now, &lt;a href=&quot;http://www.carsonsystems.com/&quot;&gt;Carson Systems&lt;/a&gt; have been developing their new web application, &lt;a href=&quot;http://www.heyamigo.net&quot;&gt;Amigo&lt;/a&gt;, and it launched a few days ago. The great thing about this is they have shared their progress through a blog, &lt;a href=&quot;http://www.barenakedapp.com&quot;&gt;BareNakedApp&lt;/a&gt;. I know it's a little late to be telling people about this, but you can have a quick look through their archives.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Press Release: Broadband website launch</title>
      <link>http://davedevelopment.co.uk/2006/09/06/press-release-broadband-website-launch.html</link>
      <pubDate>Wed, 06 Sep 2006 12:09:33 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/09/06/press-release-broadband-website-launch</guid>
      <description>&lt;p&gt;FOR IMMEDIATE RELEASE:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Looking for the right broadband deal? Look no further...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ATST Solutions launches &lt;a href=&quot;http://www.whichbroadband.net.&quot; title=&quot;Which Broadband UK&quot;&gt;http://www.whichbroadband.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today marked the launch of ATST Solutions new website, which-broadband.net. The website intends to fill a growing need for UK consumers looking for the right broadband deal in a single place.&lt;/p&gt;

&lt;p&gt;Which-Broadband.net is a simple broadband comparison site, listing broadband deals with the most important factors for making your decisions. The site avoids confusing garble, leaving readers with the straight facts.&lt;/p&gt;

&lt;p&gt;Whilst not unique, ATST Solutions owner Dave Marshall says: &quot;There's plenty of competition for sites of these kind, but most are out of date and misleading to the public. Which-Broadband intends to tie in closely with just the top few providers to keep track of the latest offers.&quot;&lt;/p&gt;

&lt;p&gt;Which-broadband.net lists broadband packages from 7 of the largest internet service providers in the country in a simple 'at a glance' format, to take a look, please vist &lt;a href=&quot;http://www.whichbroadband.net.&quot; title=&quot;Which Broadband UK&quot;&gt;http://www.whichbroadband.net&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Notes to editors:&lt;/p&gt;

&lt;p&gt;ATST Solutions is a small startup company based in the UK, who aim to deliver experise in a broad range of web development and marketing.&lt;/p&gt;

&lt;p&gt;For further information contact:
Dave Marshall
+447740346652
pr at atstsolutions dot co dot uk&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Quick bandwidth optimisation tips for Apache and PHP</title>
      <link>http://davedevelopment.co.uk/2006/09/04/quick-bandwidth-optimisation-tips-for-apache-and-php.html</link>
      <pubDate>Mon, 04 Sep 2006 11:25:55 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/09/04/quick-bandwidth-optimisation-tips-for-apache-and-php</guid>
      <description>&lt;p&gt;Here's a quick tip to optimise the &lt;abbr title=&quot;HyperText Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; response headers sent by your webserver. While being pretty useless to the average user, the Server signature and powered-by headers could be removed or at least reduced. Obviously these changes are only minor, but on a heavily loaded server such as large forums, could make a decent little saving.&lt;/p&gt;

&lt;p&gt;These two little changes...&lt;/p&gt;

&lt;p&gt;apache2.conf&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
ServerTokens Prod
&lt;/pre&gt;


&lt;p&gt;php.ini&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
expose_php = Off
&lt;/pre&gt;


&lt;p&gt;Will change the &lt;abbr title=&quot;HyperText Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; response headers on this server from:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
Server: Apache/2.0.54 (Debian GNU/Linux) PHP/4.3.10-16 \
mod_ssl/2.0.54 OpenSSL/0.9.7e mod_perl/1.999.21 Perl/v5.8.4
X-Powered-By: PHP/4.3.10-16
&lt;/pre&gt;


&lt;p&gt;To:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
Server: Apache
&lt;/pre&gt;


&lt;p&gt;That's a saving of 128 bytes. This site has served 2025 requests so far this month, so this little trick might only have saved me 253kB, but what if there had been 20,000,000 requests?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ruby on Rails - First Impressions</title>
      <link>http://davedevelopment.co.uk/2006/08/28/ruby-on-rails-first-impressions.html</link>
      <pubDate>Mon, 28 Aug 2006 11:29:15 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/08/28/ruby-on-rails-first-impressions</guid>
      <description>&lt;p&gt;I've finally gotten around to finishing the basic design on the Broadband affiliate site project I've had ongoing for a while and figured it would be nice to have a backend to add/remove, de-activate all the different packages etc. So, I decided to go crazy and have a look at &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now I'm not extremely well versed with patterns and so on, but I have a decent understanding of the MVC style architecture that seems to be popular these days and I've seen a few tutorials on &lt;a href=&quot;http://www.symfony-project.com/&quot;&gt;Symfony&lt;/a&gt;, a PHP 5 web framework which I believe is fairly similar in nature to Rails, so I figured I'd get along okay. I feel I was pretty right, in a few hours over today and yesterday I've come out with a working database driven website and administration area running on Ruby on Rails.&lt;/p&gt;

&lt;p&gt;Running &lt;a href=&quot;http://www.gentoo.org&quot;&gt;Gentoo&lt;/a&gt;, I always try and use the portage package management tool,  to be double sure on what I needed to do I had a little search on google which led me to &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/HowtoInstallOnGentooWithApache&quot;&gt;this page&lt;/a&gt;, and these commands.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
echo &quot;dev-ruby/rails mysql fastcgi&quot; &gt;&gt; /etc/portage/package.use
emerge -av rails
rails /path/to/app
&lt;/pre&gt;


&lt;p&gt;That all went well and I was sat looking at a clean rails application. I fired up the builtin webserver, &lt;a href=&quot;http://www.webrick.org/&quot;&gt;WEBrick&lt;/a&gt;, it worked, so I closed it again. Seeing as I use Apache on all my servers, I wanted to use it for the development aswell. I've never used FastCGI before, but what do you know there was an example virtual host definition in the rails &lt;tt&gt;README&lt;/tt&gt; file.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;  
  &amp;lt;VirtualHost *:80&amp;gt;
    ServerName rails
    DocumentRoot /path/application/public/
    ErrorLog /path/application/log/server.log

    &amp;lt;Directory /path/application/public/&amp;gt;
      Options ExecCGI FollowSymLinks
      AllowOverride all
      Allow from all
      Order allow,deny
    &amp;lt;/Directory&amp;gt;
  &amp;lt;/VirtualHost&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Once again, this worked a treat. I then set about creating my application, which by enlarge went along without many flaws, using a combination of the excellent &lt;a href=&quot;http://api.rubyonrails.org/&quot;&gt;Rails API&lt;/a&gt;, this &lt;a href=&quot;http://media.rubyonrails.org/video/rails_take2_with_sound.mov&quot;&gt;&lt;em&gt;Create a weblog in 15 minutes&lt;/em&gt;&lt;/a&gt; screencast and &lt;a href=&quot;http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html&quot;&gt;Rolling with Ruby on Rails&lt;/a&gt; as guidance. The biggest problem I had was creating initially trying to create the scaffolds. Not knowing RoR's naming conventions, I'd foolishly named my database tables in the singular form, ie provider rather than providers. After overcoming this, I rolled on pretty nicely.&lt;/p&gt;

&lt;p&gt;Using &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/HowToQuicklyDoAuthenticationWithLoginGenerator&quot;&gt;this page&lt;/a&gt; as guidance I used the login_generator to create a simple admin area, and the scaffolding stuff filled most of the admin pages for me, just a few tweaks here and there were required. The public face was even easier, basically allowing a few different ways to filter the list of broadband packages through one action, 'list'.&lt;/p&gt;

&lt;p&gt;As far as the language Ruby itself goes, I've barely learnt anything, basically because Rails does it all for me. The most complicated things I did code wise, was using a &lt;tt&gt;case&lt;/tt&gt; statement to change the filtering on the public packages page and this simple function for turning bytes into a more readable form.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
        def human_readable(number)
                count = 0
                while number/1024 &gt; 1
                        number = number/1024
                        count += 1
                end

                iec = ['', 'K', 'M', 'G', 'T']
                return number.to_s + iec[count]
        end
&lt;/pre&gt;


&lt;p&gt;My only gripe with this so far, is the speed. It does take forever to generate these simple pages, the built in webserver does seem to be a shade quicker, but I'd still rather use apache. I'm sure there'll be some tweaks I can make to speed the FastCGI module up, but there's no rush for that now.&lt;/p&gt;

&lt;p&gt;Hopefully I'll signup for a few affiliate programs and launch the site properly within the next few days, I don't expect to make a fortune but it's been a good little learning utility so far and I hope to use it to learn a few things about affiliate marketing.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Beautify command line CVS output with perl</title>
      <link>http://davedevelopment.co.uk/2006/08/15/beautify-command-line-cvs-output-with-perl.html</link>
      <pubDate>Tue, 15 Aug 2006 03:35:10 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/08/15/beautify-command-line-cvs-output-with-perl</guid>
      <description>&lt;p&gt;Here's a couple of little perl scripts I use on a day to day basis, they simply beautify the output of command line CVS client program. I'm not a perl programmer so I'm sure there are much better ways of doing this, any suggestions are welcome. I also haven't tested either of them on anything but cygwin/winXP, cvs 1.11.17 and perl 5.8.7.&lt;/p&gt;

&lt;h5&gt;file: &lt;a title=&quot;CVS update with colour script&quot; href=&quot;/files/scripts/cvs-update&quot;&gt;cvs-update&lt;/a&gt;&lt;/h5&gt;


&lt;p&gt;This little script simply takes the output from &lt;tt&gt;cvs update&lt;/tt&gt; and  removes most of the useless information and colours the remaining output, leaving something like this.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: red&quot;&gt;U docs/README&lt;/span&gt;
&lt;span style=&quot;color: red&quot;&gt;P docs/INSTALLM&lt;/span&gt;
&lt;span style=&quot;color: blue&quot;&gt;M docs/FAQ&lt;/span&gt;
&lt;span style=&quot;color: yellow&quot;&gt;C docs/TODO&lt;/span&gt;&lt;/pre&gt;


&lt;h5&gt;file: &lt;a title=&quot;CVS editors output in a table script&quot; href=&quot;/files/scripts/cvs-editors&quot;&gt;cvs-editors&lt;/a&gt;&lt;/h5&gt;


&lt;p&gt;This script takes the output of &lt;tt&gt;cvs editors&lt;/tt&gt; and formats the output neatly in an ascii table, like this.&lt;/p&gt;

&lt;pre class='code'&gt;
+--------------+---------+--------------------------+---------+
| File         | User    | Date                     | Host    |
+--------------+---------+--------------------------+---------+
| docs/README  | davem   | Mon Aug 14 10:04:56 2006 | lando   |
+--------------+---------+--------------------------+---------+
| docs/FAQ     | davem   | Mon Jul 31 14:38:12 2006 | lando   |
+--------------+---------+--------------------------+---------+
| docs/TODO    | davem   | Mon Jul 31 14:34:56 2006 | lando   |
+--------------+---------+--------------------------+---------+
| docs/INSTALL | davem   | Mon Jul 31 14:04:31 2006 | hansolo |
+--------------+---------+--------------------------+---------+
&lt;/pre&gt;

</description>
    </item>
    
    <item>
      <title>New domains for DaveProxy</title>
      <link>http://davedevelopment.co.uk/2006/08/14/new-domains-for-daveproxy.html</link>
      <pubDate>Mon, 14 Aug 2006 02:07:36 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/08/14/new-domains-for-daveproxy</guid>
      <description>&lt;p&gt;I registered four new domains to point to &lt;a href=&quot;http://www.daveproxy.co.uk&quot; title=&quot;DaveProxy - Free web proxy&quot;&gt;DaveProxy&lt;/a&gt;, might help some folk who have been blocked.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.dprxy.co.uk&quot;&gt;http://www.dprxy.co.uk&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.daveprxy.co.uk&quot;&gt;http://www.daveprxy.co.uk&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.dpx.org.uk&quot;&gt;http://www.dpx.org.uk&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://dvprxy.co.uk&quot;&gt;http://www.dvprxy.co.uk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    
    <item>
      <title>Upgrade to WordPress 2.04</title>
      <link>http://davedevelopment.co.uk/2006/08/03/upgrade-to-wordpress-204.html</link>
      <pubDate>Thu, 03 Aug 2006 14:19:44 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/08/03/upgrade-to-wordpress-204</guid>
      <description>&lt;p&gt;That's right I finally bit the bullit and upgraded this baby to &lt;a href=&quot;http://www.wordpress.org&quot;&gt;WordPress 2.04&lt;/a&gt;. I stayed away from the 2 release at first, just to let it get smoothed out and then just got lazy. It didn't take ten minutes, the upgrade instructions on the site being slightly overkill, mainly backing up everything, but better safe than sorry.&lt;/p&gt;

&lt;p&gt;The best thing to come out of this is I'm now using the &lt;a href=&quot;http://akismet.com&quot;&gt;Akismet&lt;/a&gt; spam blocking plugin and have been very impressed with it. Since activating it on Sunday afternoon, it's captured 160 spam comments, and successfully let the 5 genuine comments through.&lt;/p&gt;

&lt;p&gt;You'll also notice the &lt;a href=&quot;http://www.w-a-s-a-b-i.com/archives/2004/05/26/wordpress-related-entries-plugin/&quot;&gt;related posts&lt;/a&gt; links beneath all posts and you wont notice but I'm running the  &lt;a href=&quot;http://www.arnebrachhold.de/2005/06/05/google-sitemaps-generator-v2-final&quot;&gt;Google Sitemaps Generator&lt;/a&gt; aswell.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Identity Package Contest Winner</title>
      <link>http://davedevelopment.co.uk/2006/07/27/identity-package-contest-winner.html</link>
      <pubDate>Thu, 27 Jul 2006 02:05:50 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/07/27/identity-package-contest-winner</guid>
      <description>&lt;p&gt;Announced the winner of the &lt;a href=&quot;http://www.sitepoint.com/forums/showthread.php?t=403945&quot;&gt;ATST Identity contest &lt;/a&gt; on Sunday, finally got my debit card verified on &lt;a href=&quot;http://www.moneybookers.com&quot; title=&quot;Money Bookers&quot;&gt;Money Bookers&lt;/a&gt; today and the transaction is complete.&lt;/p&gt;

&lt;p&gt;The winner was &lt;a href=&quot;http://www.geniuslogo.com&quot; title=&quot;GeniusLogo&quot;&gt;GeniusLogo&lt;/a&gt;, with this logo and equivalent package.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blue.png&quot; alt=&quot;ATST Solutions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Other worthy mentions were efforts from:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.logoholik.com/&quot; title=&quot;LogoHolik&quot;&gt;LogoHolik&lt;/a&gt; with this &lt;a href=&quot;http://www.sitepoint.com/forums/showpost.php?p=2916341&amp;postcount=23&quot;&gt;entry&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Chris318 with this &lt;a href=&quot;http://www.sitepoint.com/forums/showpost.php?p=2925016&amp;postcount=84 http://www.sitepoint.com/forums/showpost.php?p=2921408&amp;postcount=62&quot;&gt;entry&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;ZidaNe with this &lt;a href=&quot;http://www.sitepoint.com/forums/showpost.php?p=2919890&amp;postcount=52&quot;&gt;entry&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Casperamy with this &lt;a href=&quot;http://www.sitepoint.com/forums/showpost.php?p=2923814&amp;postcount=74&quot;&gt;entry&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Huhknee with this &lt;a href=&quot;http://www.sitepoint.com/forums/showpost.php?p=2924863&amp;postcount=82&quot;&gt;entry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



</description>
    </item>
    
    <item>
      <title>Brainbench PHP 5 Certification</title>
      <link>http://davedevelopment.co.uk/2006/07/22/brainbench-php-5-certification.html</link>
      <pubDate>Sat, 22 Jul 2006 05:16:14 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/07/22/brainbench-php-5-certification</guid>
      <description>&lt;p&gt;Intrigued by reading about the &lt;a title=&quot;Brainbench PHP certification&quot; href=&quot;http://brainbench.com/xml/bb/common/testcenter/taketest.xml?testId=2523&quot;&gt;BrainBench PHP certifiation&lt;/a&gt; on Tobias Schlitt's and Markus Wolff's respective blogs (via &lt;a title=&quot;PlanetPHP&quot; href=&quot;http://www.planet-php.net/&quot;&gt;PlanetPHP&lt;/a&gt;), I thought I'd give it a try.&lt;/p&gt;

&lt;p&gt;To basically iterate what they both said, it's bollocks. You've got three minutes to answer each question and as long as you're quick with the online manual, most of the answers can be looked up easily. That said I didn't get them all right, so I must have missed with a couple of guesses for one's I couldn't lookup. One in particluar was a function supposedly for verifying credit card numbers, the logic was too much for me to take in, not in three minutes anyway.&lt;/p&gt;

&lt;p&gt;The code examples are filthy as well, the first one I got involved two ternary operators spread over two or three lines and similar to the Zend Certification, I think syntax highlighting would be nice on these things.&lt;/p&gt;

&lt;p&gt;I do think being able to use the manual well is valuable skill, however. I have the &lt;a title=&quot;PHP.net&quot; href=&quot;http://www.php.net&quot;&gt;PHP.net&lt;/a&gt; Manual set up as a quick search in &lt;a title=&quot;Mozilla Firefox&quot; href=&quot;http://www.getfirefox.com&quot;&gt;Firefox&lt;/a&gt;, so an average search is simply a case of hitting ctrl-t (new tab), alt-d (focus to address bar), php function_name, enter.  I do this all day long, I'm not bad at coding, but struggle to remember parameter order etc.&lt;/p&gt;

&lt;p&gt;Here's my results anyway.
&lt;img alt=&quot;Test Results&quot; src=&quot;/brainbench_test.png&quot; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Company Identity Package Contest</title>
      <link>http://davedevelopment.co.uk/2006/07/16/company-identity-package-contest.html</link>
      <pubDate>Sun, 16 Jul 2006 13:48:52 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/07/16/company-identity-package-contest</guid>
      <description>&lt;p&gt;Right then, I've finally bit the bullet and created an &lt;a href=&quot;http://www.sitepoint.com/forums/showthread.php?t=403945&quot; title=&quot;ATST indentity package design contest&quot;&gt;identity package contest&lt;/a&gt; over at &lt;a href=&quot;http://www.sitepoint.com&quot; title=&quot;SitePoint&quot;&gt;SitePoint&lt;/a&gt;. It's a contest to design a logo, letterhead and business cards for ATST Solutions which is my emerging business as a sole trader, mainly for the little bit of cash I'm making from my advertising on various web sites, but I've started a small web design contract for a friend, more on which later.&lt;/p&gt;

&lt;p&gt;I decided to do it this way for a number of reasons:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Although technically capable with some aspects of design, I lack creativity and any artistic qualities.&lt;/li&gt;
    &lt;li&gt;The excellent quality of works in the other SitePoint contests&lt;/li&gt;
    &lt;li&gt;This way lots of people get to throw ideas at me and I pick the one's I like, eventually picking the one I like most.&lt;/li&gt;
    &lt;li&gt;I wouldn't know where to start commisioning someone to do it in a none contest sense.&lt;/li&gt;
    &lt;li&gt;I think the money spent on SitePoint listings and prize money is good value for the quality you get.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Will post the winning entry when I get it, the contest ends this Friday. I'll also post links to any designers websites who made good impressions and came in close.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>PHP5 objects assigned by reference?</title>
      <link>http://davedevelopment.co.uk/2006/06/18/php5-objects-assigned-by-reference.html</link>
      <pubDate>Sun, 18 Jun 2006 03:46:51 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/06/18/php5-objects-assigned-by-reference</guid>
      <description>&lt;p&gt;I've been working with PHP5 since it's release and find it very hard to believe I haven't come across this yet. By default, in PHP5, assigning an object instance to another variable, the new variable will access the same instance, but not by reference? To quote the manual:&lt;/p&gt;

&lt;blockquote&gt;When assigning an already created instance of an object to a new variable, the new variable will access the same instance as the object that was assigned. This behaviour is the same when passing instances to a function. A new instance of an already created object can be made by cloning it.&lt;/blockquote&gt;


&lt;p&gt;Hence the code...
&lt;span style=&quot;color: #000000&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #007700&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;MyClass
&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;{
var &lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$myVariable &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color: #dd0000&quot;&gt;'1'&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;;
}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1         &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= new &lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;MyClass&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignNormally    &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignByReference &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$clone             &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= clone(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;);&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignNormally&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;myVariable &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color: #dd0000&quot;&gt;'2'&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$clone&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;myVariable &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color: #dd0000&quot;&gt;'clone'&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// 2
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignNormally&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// 2
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignByReference&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// 2
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$clone&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// clone&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1 &lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$instance1&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// NULL
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignNormally&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// 2
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$assignByReference&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// NULL
&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;var_dump&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;$clone&lt;/span&gt;&lt;span style=&quot;color: #007700&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;// clone&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #0000bb&quot;&gt;?&amp;gt;
&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Produces ...&lt;/p&gt;

&lt;p&gt;&lt;code&gt;object(MyClass)#1 (1) {
[&quot;myVariable&quot;]=&gt;
string(1) &quot;2&quot;
}
object(MyClass)#1 (1) {
[&quot;myVariable&quot;]=&gt;
string(1) &quot;2&quot;
}
object(MyClass)#1 (1) {
[&quot;myVariable&quot;]=&gt;
string(1) &quot;2&quot;
}
object(MyClass)#2 (1) {
[&quot;myVariable&quot;]=&gt;
string(5) &quot;clone&quot;
}
NULL
object(MyClass)#1 (1) {
[&quot;myVariable&quot;]=&gt;
string(1) &quot;2&quot;
}
NULL
object(MyClass)#2 (1) {
[&quot;myVariable&quot;]=&gt;
string(5) &quot;clone&quot;
}&lt;/code&gt;Had me puzzled at work for quite some time and I ended up searching the Bug reports.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DaveProxy 3.0</title>
      <link>http://davedevelopment.co.uk/2006/05/26/daveproxy-30.html</link>
      <pubDate>Fri, 26 May 2006 08:43:27 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/05/26/daveproxy-30</guid>
      <description>&lt;p&gt;Well then, a few months down the road and I've hopefully made a few more improvements to DaveProxy.&lt;/p&gt;

&lt;p&gt;First off is some modifications to the CGIProxy script, thanks to the guys over at &lt;a href=&quot;http://proxysociety.com/&quot;&gt;Proxy Society&lt;/a&gt;. It basically allows me to control which type of files can be accessed through the proxy, based on the file extension.&lt;/p&gt;

&lt;p&gt;I did have &lt;a href=&quot;http://www.squid.org&quot;&gt;Squid&lt;/a&gt; running as a httpd accelerator for a while, but in the end I decided that the benefits were not really worth the hassle. On the other hand, I can see where this type of setup could prove very useful, particularly with other CGI scripts, just not proxy one's.&lt;/p&gt;

&lt;p&gt;I also started rotating the cgi-bin folder by adding a random number to the end, changing all the configuration scripts and the index page of the site every two hours. This certainly stopped a lot of hotlinking, but stopped people from adding favourites through the site and also any incoming traffic from &lt;a href=&quot;http://proxy.org&quot;&gt;Proxy.org&lt;/a&gt;. I also tried using apache to deny any requests without referers, this worked well for a short time...&lt;/p&gt;

&lt;p&gt;The site had some major downtime recently and although I'm not entirely sure I think I figured out what happened. About three days ago, I had a massive influx of traffic, which ended with me serving thousands of 403 denied requests, which culminated in the proxy not being able to handle any real requests because apache and the proxy itself were firing that many 403's back. I personally think these requests were mainly coming from China. Pages like this &lt;a href=&quot;http://translate.google.com/translate?hl=en&amp;sl=zh-CN&amp;u=http://www.vbulletin-chinese.com/forum/archive/index.php/t-2124.html&amp;prev=/search%3Fq%3Ddaveproxy%26start%3D10%26hl%3Den%26hs%3DGbh%26lr%3D%26client%3Dfirefox-a%26rls%3Dorg.mozilla:en-US:official%26sa%3DN&quot;&gt;providing links to FreeBSD&lt;/a&gt; and not to mention all the forum pages hotlinking porn,  are just abusing the site and it's not fair on me or the genuine users. First I thought about geotargetting and deny requests, but that wouldn't help anyway. A 403 might cost me 1kB, which doesn't sound like much, but times that by thousands and my server would be crippled again. So why not drop it before it gets to Apache? A quick google search not only led me to sites listing chinese and korean 'A' class network ranges, but also to iptables scripts set to drop all traffic for them. Changed the port from SMTP to HTTP and I was in business. Even implemented this at work for our SMTP server, cut the spam in half!&lt;/p&gt;

&lt;p&gt;Add to that some more links, a news page, a links page and a little bit of promotion here and there and that's DaveProxy as of now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How I work</title>
      <link>http://davedevelopment.co.uk/2006/05/21/how-i-work.html</link>
      <pubDate>Sun, 21 May 2006 13:28:35 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/05/21/how-i-work</guid>
      <description>&lt;p&gt;Here's a quick write up about how I work, inspired by the people at &lt;a href=&quot;http://www.lifehacker.com/software/how-i-work/hack-attack-how-lifehacker-editors-work-173535.php&quot; title=&quot;Lifehacker&quot;&gt;LifeHacker&lt;/a&gt; who have been putting up similar posts.
&lt;strong&gt;
What desktop software do you use every day?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every morning I launch three programs, &lt;a href=&quot;http://www.spreadfirefox.com/?q=affiliates&amp;amp;id=76679&amp;amp;t=85&quot; title=&quot;Get Firefox&quot;&gt;Mozilla Firefox&lt;/a&gt;, &lt;a href=&quot;http://www.spreadfirefox.com/?q=affiliates&amp;amp;id=76679&amp;amp;t=179&quot;&gt;Mozilla Thunderbird&lt;/a&gt; and an RXVT terminal through &lt;a href=&quot;http://www.cygwin.org&quot;&gt;cygwin&lt;/a&gt;. My editor of choice is &lt;a href=&quot;http://www.vim.org&quot; title=&quot;Vim - Vi Improved&quot;&gt;Vim&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What web sites do you use every day?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I like to keep with my favourite feeds using &lt;a href=&quot;http://www.bloglines.com&quot; title=&quot;Bloglines&quot;&gt;Bloglines&lt;/a&gt; and I'd be lost without &lt;a href=&quot;htttp://www.google.com&quot;&gt;Google&lt;/a&gt;, &lt;a href=&quot;http://www.sitepoint.com/forums/&quot; title=&quot;Sitepoint Forums&quot;&gt;Sitepoint Forums&lt;/a&gt; and &lt;a href=&quot;http://www.php.net&quot; title=&quot;PHP&quot;&gt;PHP.net&lt;/a&gt;.
&lt;strong&gt;
What PDA/personal organizer/system do you use to keep organized?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I aren't very organised and I don't own a PDA. I do have a windows smartphone, but use it for calling people, stuff like that. I've recently been trying out the text file todo list techniques I found on &lt;a href=&quot;http://www.lifehacker.com/software/text/geek-to-live-list-your-life-in-txt-166299.php&quot; &gt;Lifehacker&lt;/a&gt; a couple of weeks ago, working alright.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Setting up an adserver</title>
      <link>http://davedevelopment.co.uk/2006/05/13/setting-up-an-adserver.html</link>
      <pubDate>Sat, 13 May 2006 05:15:19 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/05/13/setting-up-an-adserver</guid>
      <description>&lt;p&gt;I recently set up an adserver, purely so I could split an ad spot on the proxy site between two campaigns, to see which one performs better.&lt;/p&gt;

&lt;p&gt;Installing &lt;a href=&quot;http://phpadsnew.com/&quot; title=&quot;phpAdsNew&quot;&gt;phpAdsNew&lt;/a&gt;, an open-source ad-server, was very easy and their documentation is excellent.&lt;/p&gt;

&lt;p&gt;Creating the publishing zone was easy enough, then I had to create the two campaigns. The two ad networks I wanted to compare, were &lt;a href=&quot;http://www.rightmedia.com/&quot; title=&quot;RightMedia&quot;&gt;RightMedia&lt;/a&gt; and &lt;a href=&quot;http://www.bannerconnect.net/&quot; title=&quot;BannerConnect&quot;&gt;BannerConnect&lt;/a&gt;, which both use the yieldmanager software developed by RightMedia. I set these two up as Advertisers, then created a campaign for each. Then under the campaign you create a banner, which I created as HTML banners. Originally I used the standard yieldmanager tags, but this didn't seem to work properly, I don't think Internet Explorer was rendering the ads. Naturally I didn't notice at first, I don't do Internet Explorer. After changing to the Raw iFrame tags, I started getting plenty of impressions again and it worked out quite well.&lt;/p&gt;

&lt;p&gt;I'm planning to move a few other ad zones over to the adserver, it makes sense and should help my acquire more money! Next step is to get the geo-targeting going, I've got nothing to geo-target right now, but should come in useful at some stage.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New website - Keldy's Heroes</title>
      <link>http://davedevelopment.co.uk/2006/04/18/new-website-keldys-heroes.html</link>
      <pubDate>Tue, 18 Apr 2006 11:46:42 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/04/18/new-website-keldys-heroes</guid>
      <description>&lt;p&gt;I'm planning on putting a full website up for the touring hockey team I play for, Keldy's Heroes. I've just got back from the &lt;a href=&quot;http://www.blackpoolhf.com&quot;&gt;Blackpool Hockey Festival&lt;/a&gt; and got a complaint or two about the lack of the website I promised after last years tour.&lt;/p&gt;

&lt;p&gt;It's not complete at all, in fact it's only running some photo album software, &lt;a href=&quot;http://www.zenphoto.org&quot;&gt;zenphoto&lt;/a&gt;, which was reccomended by a colleague. It seems small and quick, just what I needed really. DNS should be up by the time anybody reads this and hopefully last years photo's will soon be available.&lt;/p&gt;

&lt;p&gt;I plan to add a little bit of team history, news and of course a forum, mainly for players past and present to keep in touch.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.keldysheroes.co.uk&quot; title=&quot;Keldy's Heroes&quot;&gt;http://www.keldysheroes.co.uk&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ZCE Diploma Arrives</title>
      <link>http://davedevelopment.co.uk/2006/04/03/zce-diploma-arrives.html</link>
      <pubDate>Mon, 03 Apr 2006 14:44:12 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/04/03/zce-diploma-arrives</guid>
      <description>&lt;p&gt;Finally received my diploma from Zend today. I passed the exam way back in November last year and had emailed Zend twice asking politely, when I would be receiving it, but never heard back from them.&lt;/p&gt;

&lt;p&gt;It appears to have taken the best part of nine weeks to get here, for some reason they've marked it 'Surface Transportation Only.'&lt;/p&gt;

&lt;p&gt;The diploma came in a little frame and I got a couple of stickers to go with it. Apparently I can claim some free ZCE business cards from some online company aswell.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Vim, CTAGS and PHP 5</title>
      <link>http://davedevelopment.co.uk/2006/03/13/vim-ctags-and-php-5.html</link>
      <pubDate>Mon, 13 Mar 2006 04:43:20 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/03/13/vim-ctags-and-php-5</guid>
      <description>&lt;p&gt;I've just discovered &lt;a href=&quot;http://ctags.sourceforge.net/&quot;&gt;CTAGS&lt;/a&gt;, thanks to the&lt;a href=&quot;http://www.oualline.com/vim/10/top_10.html&quot;&gt;Top 10 things Vi user need to know about Vim&lt;/a&gt; list.&lt;/p&gt;

&lt;blockquote&gt;Ctags generates an index (or tag) file of language objects found in source files that allows these items to be quickly and easily located by a text editor or other utility. A tag signifies a language object for which an index entry is available (or, alternatively, the index entry created for that object).&lt;/blockquote&gt;


&lt;p&gt;To use CTAGS with PHP 5, I downloaded the CTAGS source code, and &lt;a href=&quot;http://blog.bitflux.ch/archive/ctags_for_php.html &quot;&gt;this&lt;/a&gt; patch. Bascially the patch adds capabilities for the private, protected and public &lt;a href=&quot;http://www.php.net/manual/en/language.oop5.visibility.php&quot; title=&quot;PHP 5 - Visibility&quot;&gt;visibilty&lt;/a&gt; keywords.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# wget http://kent.dl.sourceforge.net/sourceforge\
/ctags/ctags-5.5.4.tar.gz&lt;/p&gt;

&lt;h1&gt;tar -zxvf ctags-5.5.4.tar.gz&lt;/h1&gt;

&lt;h1&gt;wget http://svn.bitflux.ch/repos/public/misc/ctags-php5.patch&lt;/h1&gt;

&lt;h1&gt;mv ctags-php5.patch ctags-5.5.4&lt;/h1&gt;

&lt;h1&gt;cd ctags-5.5.4&lt;/h1&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now patch the &lt;em&gt;php.c&lt;/em&gt; file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# patch php.c ctags-php5.patch&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Configure build and install CTAGS&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# ./configure&lt;/p&gt;

&lt;h1&gt;make&lt;/h1&gt;

&lt;h1&gt;make install&lt;/h1&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;CTAGS is now installed, we can start to use it. I'd recommend creating tag file for different projects seperately, rather than one big one in your home folder or something. So move to your folder of choice and create the tags file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# cd /path/to/your/project&lt;/p&gt;

&lt;h1&gt;ctags -R&lt;/h1&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This may take a while depending on how many files you have. Once it is done, you're ready to start using CTAGS with Vim. The '-t' option for Vim opens the file containing that tag. So..&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# vim -t 'MyClass'
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;... would open the MyClass.php class definition file. Once inside a file, hitting &lt;em&gt;ctrl-]&lt;/em&gt; while the cursor is over a function/class name, Vim will attempt to open the file with that tag. Pressing &lt;em&gt;ctrl-t&lt;/em&gt; will take you back a step.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>MySQL 5 Certification</title>
      <link>http://davedevelopment.co.uk/2006/03/08/mysql-developer-certification-exams-booked.html</link>
      <pubDate>Wed, 08 Mar 2006 13:04:04 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/03/08/mysql-developer-certification-exams-booked</guid>
      <description>&lt;p&gt;Over the last few days I've had to send a couple of emails to customer support at &lt;a href=&quot;http://www.vue.com/&quot; title=&quot;Pearson Vue&quot;&gt;Pearson Vue&lt;/a&gt;, basically because I couldn't find a way of booking any exam except the one I have already passed, the ZCE. Eventually, once I tried using the site in IE, I got a javascript alert telling me I needed a seperate web account to register for &lt;a href=&quot;http://www.mysql.org&quot; title=&quot;MySQL&quot;&gt;MySQL&lt;/a&gt; exams. Unfortunately, when I tried to create a new web account, I was told that they already had a web account matching my details and would I like them to reset my password!&lt;/p&gt;

&lt;p&gt;Anyways, they responded to my second email quite quickly and sure enough I logged in and booked the two &lt;a href=&quot;http://www.mysql.com/training/certification/50/&quot; title=&quot;MySQL 5 Certifications&quot;&gt;MySQL Developer&lt;/a&gt; Certification exams, the first on 10th April and the second 8th May. Hopefully this will put me under a bit of pressure and make me pick up the &lt;a href=&quot;http://www.amazon.co.uk/exec/obidos/redirect?link_code=ur2&amp;tag=davedvd-21&amp;camp=1634&amp;creative=6738&amp;path=ASIN%2F0672328127%2Fqid%253D1141861211&quot;&gt;Certification Guide&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.co.uk/e/ir?t=davedvd-21&amp;amp;l=ur2&amp;amp;o=2&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;  once again.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>JBoss and Gentoo</title>
      <link>http://davedevelopment.co.uk/2006/03/02/jboss-and-gentoo.html</link>
      <pubDate>Thu, 02 Mar 2006 04:55:05 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/03/02/jboss-and-gentoo</guid>
      <description>&lt;p&gt;After learning and using Java though my 3 years of university, I haven't touched the stuff since. Not because I don't like it, just because I haven't needed to. After a meeting at work the other day I decided to pull my finger out and re-educate myself, particularly towards the enterprise stuff, which they didn't teach me at Uni. If they had I'd probably be loaded right now.&lt;/p&gt;

&lt;p&gt;Finding a &lt;a href=&quot;http://www.tusc.com.au/tutorial/html/&quot;&gt;tutorial&lt;/a&gt;, I sat down at my desktop machine and set about creating my first J2EE application. I'm a big fan of &lt;a href=&quot;http://www.gentoo.org&quot; title=&quot;Gentoo&quot;&gt;Gentoo&lt;/a&gt; Linux and try to use it's portage package management as much as possible, making it easy to maintain my system, so rather than download &lt;a href=&quot;http://www.jboss.org&quot; title=&quot;JBoss&quot;&gt;JBoss&lt;/a&gt; like the tutorial says, I simply.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# emerge jboss&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This went fine, as did firing up jboss and going to the console through my browser. Then I stumbled. Trying to invoke 'startDatabaseManager' wouldn't seem to work. It said it did, but the applet never appeared. An hour later, after customising the deploy XML file for HyperSonic, I was closer to having the database the way it needs to be, but still couldn't get the applet to fire up. I googled for a while and found a handful of people having the same problems, but never for the same reason. In the end I gave up.&lt;/p&gt;

&lt;p&gt;The thing is, right now I'm interested in the J2EE side of things, not so much the database, so it's kind of annoying getting stuck so early. I'll spend some time tonight trying to access the HSQLDB another way, if not I'll try and adapt the tutorial to use &lt;a href=&quot;http://www.mysql.org&quot; title=&quot;MySQL AB&quot;&gt;MySQL&lt;/a&gt;!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Total Web Server requests - AWK one liner</title>
      <link>http://davedevelopment.co.uk/2006/02/23/total-web-server-requests-awk-one-liner.html</link>
      <pubDate>Thu, 23 Feb 2006 01:18:20 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/02/23/total-web-server-requests-awk-one-liner</guid>
      <description>&lt;p&gt;I've just started getting in to AWK, due to the massive traffic load on &lt;a href=&quot;http://www.daveproxy.co.uk&quot;&gt;DaveProxy&lt;/a&gt;.  The one below is set to run on an Combined log format, but I use it on the &lt;a href=&quot;http://www.squid-cache.org/&quot; title=&quot;Squid Cache&quot;&gt;Squid&lt;/a&gt; logs, which act as a HTTPD accelerator.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Total requests:  429972
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Not bad in just under 24 hours.&lt;/p&gt;

&lt;p&gt;Here it is anyway, should read your access log, print individual IP addresses along with the number of requests and a grand total at the bottom. The first part I read from a &lt;a href=&quot;http://www.linux.com&quot;&gt;Linux.com&lt;/a&gt; article (I think) and I added the sum at the end. I am pretty new to this so any suggestions for improvement or variations would be appreciated.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cat access.log | awk '{print $1}' | sort | uniq -c | sort -n | awk 'sum = sum + $1;END {print &quot;\nTotal request
s: &quot;,sum}'&lt;/code&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My first XML + XSLT</title>
      <link>http://davedevelopment.co.uk/2006/02/21/my-first-xml-xslt.html</link>
      <pubDate>Tue, 21 Feb 2006 03:27:11 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/02/21/my-first-xml-xslt</guid>
      <description>&lt;p&gt;Been playing around a little at work with these. I was given a rather mundane task of presenting a list of constants, pulled out of the sourcecode for our current project on the fly for use by the developers. The php code to do so and generate the XML took about twenty minutes and then I set about investigating XSLT.&lt;/p&gt;

&lt;p&gt;Using an &lt;a href=&quot;http://www.w3schools.com/xsl/&quot;&gt;XSLT Tutorial&lt;/a&gt; and the source code from &lt;a href=&quot;http://sourceforge.net/projects/gstoolbox&quot;&gt;Google Sitemaps Stylesheets&lt;/a&gt;, I knocked up a couple of Stylesheets, including one with sortable table columns. I couldn't get the alternate stylesheet thing to work with firefox though, don't know if I was doing anything wrong.&lt;/p&gt;

&lt;p&gt;Would post some code but I might get in trouble.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>99 Bottles of Beer - PHP 5</title>
      <link>http://davedevelopment.co.uk/2006/02/20/99-bottles-of-beer-php-5.html</link>
      <pubDate>Mon, 20 Feb 2006 05:28:58 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/02/20/99-bottles-of-beer-php-5</guid>
      <description>&lt;p&gt;Got an email today from &lt;a href=&quot;http://www.99-bottles-of-beer.net/&quot;&gt;99 bottles of beer.net&lt;/a&gt; regarding the acceptance of my &lt;a href=&quot;http://www.99-bottles-of-beer.net/language-php5-883.html&quot;&gt;entry&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I wrote it way back in September, I think because the other PHP5 examples didn't show much more than what could've been done in PHP4.x and because I was bored.&lt;/p&gt;

&lt;p&gt;Basically there website is collection of programs that produce the lyrics to the '99 bottles of beer' song. Apparently there are currently over 904 variations. This &lt;a href=&quot;http://www.99-bottles-of-beer.net/language-perl-737.html&quot;&gt;one&lt;/a&gt; has to be my favourite of the one's I've seen, despite being generated by a script.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Google Adsense Account Disabled</title>
      <link>http://davedevelopment.co.uk/2006/02/13/google-adsense-account-disabled.html</link>
      <pubDate>Mon, 13 Feb 2006 11:58:25 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/02/13/google-adsense-account-disabled</guid>
      <description>&lt;p&gt;Apparently because of 'Invalid clicks' my google adsense account has been banned. I'm a little dissapointed to say the least, as far as I know I've done nothing wrong. Here's a copy of the email they sent me.&lt;/p&gt;

&lt;blockquote&gt;Hello David Marshall,

It has come to our attention that invalid clicks have been generated on
the Google ads on your site(s). We have therefore disabled your Google
AdSense account. Please understand that this step was taken in an
effort to protect the interest of the AdWords advertisers.

A publisher's site may not have invalid clicks on any ad(s), including
but not limited to clicks generated by:

- a publisher on his own web pages
- a publisher encouraging others to click on his ads
- automated clicking programs or any other deceptive software
- a publisher altering any portion of the ad code or changing the
layout, behavior, targeting, or delivery of ads for any reason

Practices such as these are in violation of the Google AdSense Terms
and Conditions and programme polices, which can be viewed at:

https://www.google.com/adsense/localized-terms?hl=en_GB
https://www.google.com/adsense/policies?hl=en_GB

Publishers disabled for invalid click activity are not allowed further
participation in AdSense and do not receive any further payment. The
earnings on your account will be properly returned to the affected
advertisers.

Sincerely,

The Google AdSense Team&lt;/blockquote&gt;


&lt;p&gt;Needless to say I have appealed against this, things had just started to get going and I was earning enough to pay for my hosting. The chances of getting it revoked are slim at best, but it's got to be worth a try.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>UK PHP Conference</title>
      <link>http://davedevelopment.co.uk/2006/01/30/uk-php-conference.html</link>
      <pubDate>Mon, 30 Jan 2006 07:57:40 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/01/30/uk-php-conference</guid>
      <description>&lt;p&gt;There's a &lt;a href=&quot;http://www.php.net&quot; title=&quot;PHP Hypertext PreProcessor&quot;&gt;PHP &lt;/a&gt; conference going down in London next week, I was hoping to attend for a couple of reasons, firstly because I've never been to a conference and secondly because they've got some pretty renowned speakers showing up. Unfortunately I've fractured my thumb and have an appointment at the fracture clinic that day, not to mention I can't drive. I'd reccomend anyone interested get themselves a ticket and check it out, doesn't happen all that often.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.phpconference.co.uk/&quot; title=&quot;PHP Conference UK&quot;&gt;PHP Conference UK&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DaveProxy 2.0</title>
      <link>http://davedevelopment.co.uk/2006/01/30/daveproxy-20.html</link>
      <pubDate>Mon, 30 Jan 2006 07:43:54 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/01/30/daveproxy-20</guid>
      <description>&lt;p&gt;Just spent an hour or so tweaking the server running DaveProxy, mainly the introduction of &lt;a href=&quot;http://perl.apache.org/&quot;&gt;mod_perl&lt;/a&gt; and a couple of little tweaks to &lt;a href=&quot;http://apache.org&quot;&gt;Apache&lt;/a&gt;. Both together it should help keep it up during the worst periods of traffic.&lt;/p&gt;

&lt;p&gt;I decided I'd take this course of action rather than moving over to &lt;a href=&quot;http://www.whitefyre.com/poxy/&quot;&gt;PHProxy&lt;/a&gt;, although CGIProxy is very heavy on resources, using mod_perl should cut out the perl interpreter instantiation for every request and also allows easier monitoring using &lt;a href=&quot;http://www.tildeslash.com/monit/&quot;&gt;Monit&lt;/a&gt;. While PHProxy is better on the resources side of things, CGIProxy handles more features.&lt;/p&gt;

&lt;p&gt;Depending on how well it goes over the next week, I may introduce &lt;a href=&quot;http://squid.org&quot;&gt;squid&lt;/a&gt; as a cache between Apache and clients.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New theme</title>
      <link>http://davedevelopment.co.uk/2006/01/22/new-theme.html</link>
      <pubDate>Sun, 22 Jan 2006 08:30:05 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/01/22/new-theme</guid>
      <description>&lt;p&gt;So this is the wordpress theme I've been working on. It looks alot worse on a page full of posts, maybe I should fill up my dummy wordpress install. I definitely need some more separation between posts. I'm gonna leave it on here for now as it is, will offer the code once I'm happy with it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Book Review: Essential PHP Security </title>
      <link>http://davedevelopment.co.uk/2006/01/22/book-review-essential-php-security.html</link>
      <pubDate>Sun, 22 Jan 2006 07:55:30 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2006/01/22/book-review-essential-php-security</guid>
      <description>&lt;p&gt;I read this book some time ago and as well as re-emphasizing some of the things I already knew about PHP security, it certainly brought a few finer points to my attention.&lt;/p&gt;

&lt;p&gt;While the book is quite small at little over a hundred pages, what you get is pure. There's no sidetracking onto this and that, this book is targeted one hundred percent at PHP development.&lt;/p&gt;

&lt;p&gt;I'm no book expert, but I would definitely recommend this book to aspiring PHP developers and think it would also benefit some of the more experienced folk out there.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/059600656X/ref=as_li_ss_il?ie=UTF8&amp;tag=davedvd-20&amp;linkCode=as2&amp;camp=217145&amp;creative=399369&amp;creativeASIN=059600656X&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=059600656X&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=davedvd-20&amp;ServiceVersion=20070822&quot; &gt;&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=davedvd-20&amp;l=as2&amp;o=1&amp;a=059600656X&amp;camp=217145&amp;creative=399369&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DaveProxy</title>
      <link>http://davedevelopment.co.uk/2005/12/04/daveproxy.html</link>
      <pubDate>Sun, 04 Dec 2005 23:53:47 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2005/12/04/daveproxy</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.daveproxy.co.uk&quot;&gt;DaveProxy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DaveProxy, my new online proxy site is up and running. It uses &lt;a href=&quot;http://www.jmarshall.com/tools/cgiproxy/&quot;&gt;CGIProxy&lt;/a&gt;, a free Perl proxy script. The design took me not long and I used &lt;a href=&quot;http://gug.sunsite.dk/?page=tutorials&quot;&gt;GUG Tutorials&lt;/a&gt; for the graphics. It'll stay up while I've got the bandwidth available, unless it starts making me loads of money and then I'll keep it up.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bug in google?</title>
      <link>http://davedevelopment.co.uk/2005/11/30/bug-in-google.html</link>
      <pubDate>Wed, 30 Nov 2005 02:40:47 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2005/11/30/bug-in-google</guid>
      <description>&lt;p&gt;I think I just found what might be a bug in google.&lt;/p&gt;

&lt;p&gt;I was trying to search for the correct way to make a Post request to a webserver by searching for 'http post'. I accidently typed 'http postt'. The usually very helpful 'Did you mean' link was broken. Naturally I pressed back and clicked it again, being too lazy to go back to the search bar and again it was broken. Looking at the URL, something didn't look right.&lt;/p&gt;

&lt;p&gt;I tried a couple more searches with spelling mistakes and it seems that if the first word is 'http', the url doesn't get formed properly. See for yourself below.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.google.co.uk/search?q=http+postt&quot;&gt;Google Search for 'http postt'&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Zend Certified Engineer</title>
      <link>http://davedevelopment.co.uk/2005/11/28/zend-certified-engineer.html</link>
      <pubDate>Mon, 28 Nov 2005 08:26:20 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2005/11/28/zend-certified-engineer</guid>
      <description>&lt;p&gt;During my well earned week off work, I studied for, took and passed the &lt;a href=&quot;http://www.zend.com/store/education/certification/zend-php-certification.php&quot;&gt;Zend Certified Engineer&lt;/a&gt; Exam.&lt;/p&gt;

&lt;p&gt;I was quite suprised when the words 'Congratulations...' appeared on the screen right after I pressed the 'End Exam' button, not because I thought I'd failed but because I was expecting to have to wait for the results. One guy had written that he had to wait two weeks to find out.&lt;/p&gt;

&lt;p&gt;The exam went fine really and I felt reasonably confident.&lt;/p&gt;

&lt;p&gt;I'd definitely recommend it to any reasonably experienced PHP developers out there. I've only been doing PHP about 18 months and only the last 12 or so full time.&lt;/p&gt;

&lt;p&gt;One thing I would say about the exam, would it harm to have syntax highlighting on the example code? After coding for so long in environments like &lt;a href=&quot;http://www.vim.org&quot;&gt;Vim&lt;/a&gt; and &lt;a href=&quot;http://www.jedit.org&quot;&gt;jEdit&lt;/a&gt;, I find it difficult to actually read code. Obviously highlighting errors would be out of the question. Another thing might be the use of better variable names within the example code, maybe using real world examples rather then $my_value.&lt;/p&gt;

&lt;p&gt;Passing the exam has spurred me on to try the &lt;a href=&quot;http://www.mysql.com/training/certification/&quot;&gt;MySQL Certification&lt;/a&gt; ordered the books from Amazon and they arrived today. I also bought &lt;em&gt;Chris Shiflett's Essential PHP Security&lt;/em&gt;, once I've had a look at them both I'll post thoughts and reviews.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://zend.com/store/education/certification/authenticate.php?ClientCandidateID=ZEND002622&amp;RegistrationID=212933867&quot;&gt;Certificate Authentication&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Welcome to DaveDevelopment</title>
      <link>http://davedevelopment.co.uk/2005/11/28/hello-world.html</link>
      <pubDate>Mon, 28 Nov 2005 08:05:42 nil</pubDate>
      <author>dave.marshall@atstsolutions.co.uk (Dave Marshall)</author>
      <guid>http://davedevelopment.co.uk/2005/11/28/hello-world</guid>
      <description>&lt;p&gt;DaveDevelopment is going a place for me to log anything and everything to do with the software and web development work I do, along with other IT related items I come across on  the internet.&lt;/p&gt;

&lt;p&gt;Maybe I'll teach someone something, maybe others will point out all the mistakes I'm making.&lt;/p&gt;

&lt;p&gt;It's not looking upto much now, I'll probably adapt the theme I made for &lt;a href=&quot;http://www.davedvd.co.uk&quot;&gt;DaveDVD&lt;/a&gt; and get it up on here at somepoint and I'll try to write some about pages too.&lt;/p&gt;
</description>
    </item>
    

  </channel> 
</rss>
