Outputting results in different formats with ZF

So no doubt somewhere on your site, you’ll have a page displaying a list of items or whatnot. In this example it’s a search results page.
We’ll have a controller action with a corresponding view (in my case its the searchAction() )
We have a view file that uses HTML markup with a PHP foreach loop to iterate through each row in the result.

But who says we want HTML? We could equally be asking for XML, JSON, CSV, anything!

This is where Zend Framework’s context switcher comes into use. It’s really simple!

In your init() method of your controller class, use something like this:

public function init()
         // initialize context switch helper
         $contextSwitch = $this->_helper->getHelper('contextSwitch');
         $contextSwitch->addActionContext('search', 'xml')

This allows us to use the URL parameter ?format=xml or /format/xml
We need a different view instead of search.phtml, so create search.xml.phtml

// create XML document 
$dom = new DOMDocument('1.0', 'utf-8');   
// create root element 
$root = $dom->createElementNS( 'http://yoursite, 'del:document'); 
// convert to SimpleXML 
$xml = simplexml_import_dom($dom);   
// add summary element 
$xml->addChild('matches', count($this->results)); 
$xml->addChild('searchTime', time());   
// add resultset elements 

$results = $xml->addChild('results'); 
foreach ($this->results as $r) 
$result = $results->addChild('result');   
$result->addChild('id', $this->escape($r->id));   
$result->addChild('name', $this->escape($r->name));   
$result->addChild('age', $this->escape($r->age));   
$result->addChild('height', $this->escape($r->height));   
$result->addChild('country', $this->escape($r->Country));   
$skills = $result->addChild('skills');   
$skills->addChild('primary', $this->escape($r->primary));
$skills->addChild('secondary', $this->escape($r->secondary)); 
// return output
 echo $xml->asXML();

Now we can browse to /index/search or /index/search/format/xml and get our results displayed in a custom format! Nose in to the Zend Docs to find out more! 😀

Zend_Date Problems with MySQL

Have you ever seen this problem?

I had a MySQL Date in my DB (2012-08-31). This is the 31st of August.

$expirydate = new Zend_Date($mysql_date);
 echo $expirydate;

Returned 31st August as expected.

But if the date is the 4th August (2012-08-04), the same code as above will echo out the 8th April!
Zend_Date automatically tries to guess the format, and mistakenly guessed Y/d/m !
I came across this problem when I tried to compare dates:

 $expirydate = new Zend_Date($mysql_date);
 $today = new Zend_Date();
     //today is beyond expiry date

The Zend Docs weren’t very clear, and i thought maybe it should have been the other way around, $expirydate->isLater($today)
But it’s not.

All that is required is to set the format in the constructor. For MySQL Dates, the format is ISO_8601:

$expirydate = new Zend_Date($mysql_date,Zend_Date::ISO_8601);

Problem solved. The moral of the story? Make sure you declare the format of the dates!!

Setting up Doctrine with Zend Framework

So you have set up doctrine and put it in your servers php library include path. You’ll need this to be in your applications library folder for when you upload it, but rather than copy it in wasting disk space, we’ll symlink it:

ln -s /usr/lib/php/Doctrine ~/Sites/your-site/library/Doctrine

Now lets configure Zend. Open application.ini and bung this stuff in:

autoloaderNamespaces[] = "Doctrine_"
resources.db.adapter = PDO_MYSQL
doctrine.dsn = "mysql://USER:PASS@localhost/DATABASE"

This lets it know about autoloading classes, the type of database adapter we use, and the connection settings. (Be sure to replace USER PASS & DATABASE with your credentials).

Next we initialise Doctrine in the bootstrap:

public function _initDoctrine()
    $manager = Doctrine_Manager::getInstance();
    $manager->setAttribute(    Doctrine_Core::ATTR_MODEL_LOADING,        Doctrine_Core::MODEL_LOADING_CONSERVATIVE);
    $config = $this->getOption('doctrine');
    $conn = Doctrine_Manager::connection($config['dsn'],'doctrine');
    return $conn;

If all is going well then we should be able to test it out and get a list of databases on the server. In the controller and action of your choosing, try the following out:

// get doctrine manager
 $manager = Doctrine_Manager::getInstance();     
// get connection
$conn = Doctrine_Manager::connection( 'mysql://root@localhost/bzf:[123456]', 'doctrine');
// get databases
$this->view->databases = $conn->import->listDatabases();