Wednesday, November 28, 2012

Route default is not defined

Working this long with Zend Framework makes me do things that have become a real routine and I don't pay much attention to it. So when I just add few custom routes to my Zend Framework application, I don't make a big fuss out of it. But apparently people do struggle with it. They get messages like this:

Zend_Controller_Router_Exception: Route default is not defined

Apparently when you create custom routes, Zend Framework "forgets" about the default route, causing this error to appear.

To quickly resolve this issue, you just open up application/Bootstrap.php and add the following to your routines:

    protected function _initDefaultRoutes()
    {   
        $frontController = Zend_Controller_Front::getInstance();
        $frontController->getRouter()->addDefaultRoutes();
    }   

If you already have routine for loading routes, just ensure you add the default routes!

    protected function _initRouteSetup()
    {   
        $frontController = Zend_Controller_Front::getInstance();
        $router = $frontController->getRouter();
        $config = new Zend_Config_Ini('/path/to/config.ini', APPLICATION_ENV);
        $router->addConfig($config, 'routes');

        // ensure you load the default routes as well!!!
        $router->addDefaultRoutes();
    }

With this blog article I hope to save a bunch of people a lot of time looking for an example and get on with building awesome applications.



Tuesday, November 13, 2012

Learning lessons at ZendUncon

In my previous post I already mentioned Sebastian Jerzy Wilczyński (@dj_sebastian_w) and his uncon session "Unit Testing for Databases using fixtures and phpunit". It made me wonder how much difference it would make if you use fixtures instead of testing database interactions using predefined sets of data.

Since I work a lot with Zend Framework I was looking at how I could use fixtures and mock objects to follow Sebastian's guidelines. So I gave it a try. This is what I came up with.

I use the domain model design pattern for accessing data storages with Zend Framework so this means I have a model (Order_Model_Order) which is the representation of my data object, a mapper (Order_Model_OrderMapper) to connect my model with an underlying data storage backend and a table gateway object (Order_Model_DbTable_Order) to link everything to the database. The object we're going to focus on is Order_Model_OrderMapper as this is the link that connects my model to the database.

At first I start my test class with fixtures.

<?php

class Order_Model_OrderMapperTest extends PHPUnit_Framework_TestCase
{
    protected $_order = array (
        0 => array (
            'id'             => 1,
            'status'         => 0,
            'price'          => 2499.95,
            'currency'       => 'USD',
            'exchange_rate'  => 1.2714,
            'vat_id'         => 3,
            'vat_percentage' => 0.00,
            'created_by'     => 400,
            'created_at'     => '2012-02-29 10:11:12',
            'updated_by'     => 303,
            'updated_at'     => '2012-11-04 03:01:01',
        ),
        1 => array (
            'id'             => 1,
            'status'         => 0,
            'price'          => 10000.00,
            'currency'       => 'EUR',
            'exchange_rate'  => 1.00,
            'vat_id'         => 1,
            'vat_percentage' => 21.00,
            'created_by'     => 400,
            'created_at'     => '2012-02-29 10:11:12',
            'updated_by'     => 303,
            'updated_at'     => '2012-11-04 03:01:01',
        ),
    );
}

The next thing we need to come up with is how to mock out the data gateway as we don't want to connect to the database of course. Because my mapper class Order_Model_OrderMapper has 2 methods to set and retrieve the data gateway it's easy to flip in and out the data gateway object. Here's my Order_Model_OrderMapper class:

<php
class Order_Model_OrderMapper
{
    /**
     * @var Zend_Db_Table_Abstract
     */
    protected $_dbTable;
    /**
     * Sets the data gateway for this Mapper class
     * 
     * @param Zend_Db_Table $dbTable
     * @throws In2it_Model_Exception
     */
    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            if (!class_exists($dbTable)) {
                throw new In2it_Model_Exception(
                    'Non-existing data gateway provided'
                );
            }
            $dbTable = new $dbTable;
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new In2it_Model_Exception('Invalid data gateway provided');
        }
        $this->_dbTable = $dbTable;
    }
    /**
     * Retrieves the data gateway class from this Mapper class
     * 
     * @return Zend_Db_Table
     * @throws In2it_Model_Exception 
     */
    public function getDbTable()
    {
        if (!isset ($this->_dbTable)) {
            throw new In2it_Model_Exception('Data gateway not set');
        }
        return $this->_dbTable;
    }

    ...
}

All we need to do now is create a mock object that we can inject in our mapper test so we don't need to connect to the database in order to test our mapper logic.

public function testOrderMapperCanFindSingleItem()
{
    $order = new Order_Model_Order();
    $orderMapper = new Order_Model_OrderMapper();
        
    $mockDb = $this->getMock('Order_Model_DbTable_Order', array ('find'));
    $mockDb->expects($this->atLeastOnce())
           ->method('find')
           ->will($this->returnValue(new ArrayIterator($this->_order)));
    $orderMapper->setDbTable($mockDb);

    $orderMapper->find($order, 1);
    $this->assertEquals($this->_order[0], $order->toArray());
}

So we create our $mockDb object replacing our data gateway object Order_Model_DbTable_Order, and by overriding the find method we can now control how we want this method to operate. By returning an ArrayIterator object, we can use the iterator method current() which is used by the find method in our mapper class. All that's left is to find our order and assert it's the same as our fixture.

I hope this might give a few ideas on saving time running your tests. The less you have expensive connections, the quicker your tests will execute.

Sunday, November 11, 2012

ZendCon 2012

October is often the month where all PHP businesses look towards sunny California, because it's ZendCon time! This year was no exception and it was a true blast. And ZendCon means not just 4 days of PHP goodness but also 2 days and a half of Uncon power. And this year I had the honour and pleasure to be in charge of the ZendUncon sessions.

Because my involvement in those uncon sessions, I missed most of the regular tracks. But on the bright side I was able to discover new speakers and was sitting in a few awesome sessions I would like to recommend here.

Let me explain the idea behind uncon sessions first, so you at least have a good grasp of the importance of these sessions. An uncon session is different from regular conference sessions because they are not scheduled and can be given by anybody. It's a great way for conference attendees to give a talk or a round table discussion. For the first situation, people can learn how to speak in public and get their first steps in talking at conferences. It's also a solution for open-source project leads to teach and answer questions regarding their projects.


Every day of the conference a clean registration board was set up, and people could select a specific time they wanted to run an uncon session. Of course this meant that availability is a "first-come, first-serve" kind of thing. Early people were able to select the best slots, because they could compare their uncon session with the conference schedule and pick a slot when none of the regular conference sessions was of interest for the speaker.

Back to the ZendUncon sessions of ZendCon 2012. Three days of uncon goodness, making it an unforgettable event. Let me highlight a couple of remarkable talks I've seen during these three days, which I can highly recommend to have at any given PHP conference.

Stefan Koopmanschap (@skoop) with "Conference Speaking 101" where he gives a whole bunch of tips and concepts anyone could use as advice for speaking at conferences. Even the regular speakers!

First time speaker Sebastian Jerzy Wilczyński (@dj_sebastian_w) with "Unit Testing for Databases using fixtures and phpunit" where he gives a very interesting point of view for testing database interactions using fixtures without reaching the database.

Best talk was given by Lorna Mitchel (@lornajane) with "Git + Github: everything you need to know!" with a standing room and enormous positive feedback.

Elizabeth Marie Smith (@auroraeosrose) was giving a true community driven talk "Mentoring Developers (and phpmentoring.org)" where she explained why and how experienced developers could take mentorship to assist and train developers seeking mentoring (apprentices). If you're in a situation where you're looking for mentorship, please visit phpmentoring.org for more information.

If you're interested in the whole ZendUncon series, you can find all the talks and most of the slides on the joind.in page for ZendUncon.
Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License.