1

Caching Zend_Gdata Auth Across Pages

Posted (Updated ) in PHP

I’ve been working with the Zend_Gdata tools lately to perform various Google Calendar operations. One thing I’ve noticed, though, is that there are no tutorials on how to cache the auth request between pages. Caching the authentication would result in one less expensive operation to an external server upon each new file request (The retrieving of a new, working Zend_Gdata_HTTPClient object). Figuring out how to accomplish this seemingly simple task proved a little more difficult than I’d have liked and ironically ended up being very simple 🙂

Initially I attempted caching the entire Zend_Gdata_Calendar object to the database (Using my Doctrine Session Driver for Kohana 3) like so:

//Look for DB cache
$this->service = Session::instance('doctrine')->get('google_calendar');
 
//No cache found
if ( !$this->service )
{
	// Parameters for ClientAuth authentication
	$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
 
	// Create an authenticated HTTP client
	$client = Zend_Gdata_ClientLogin::getHttpClient($this->_guser, $this->_gpassword, $service);
 
	// Create an instance of the Calendar service
	$this->service = new Zend_Gdata_Calendar($client);
 
	//Cache to DB
	Session::instance('doctrine')->set('google_calendar', $this->service);
}

This caused a strange quirk with Kohana’s session class. The object would save (I’m assuming correctly) but if you attempted to load it, it would be overwritten with a session-encoded empty string resulting in a null value being retrieved. After a few more failed attempts, I decided to dig through the Zend_Gdata_ClientLogin getHttpClient function to determine exactly how it worked. From this I came across getClientLoginToken() and setClientLoginToken() which in turn led me to this rewrite:

$clientLoginToken = Session::instance('doctrine')->get('google_calendar_client');
 
if ( $clientLoginToken )
{
	require_once 'Zend/Uri/Http.php';
	$client = new Zend_Gdata_HttpClient();
	$client->setClientLoginToken( $clientLoginToken );
}
else
{
	// Create an authenticated HTTP client
	$client = Zend_Gdata_ClientLogin::getHttpClient($this->_guser, $this->_gpassword, $service);
 
	//Cache to DB
	Session::instance('doctrine')->set('google_calendar_client', $client->getClientLoginToken() );
}

This version is much better than the first in that it involves storing only a string and not an entire serialized object in the DB.

For those wanting the complete code for a calendar with cached auth, I’ve provided it below:

require "Zend/Loader.php";
Zend_Loader::loadClass('Zend_Gdata_Calendar');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
 
// Parameters for ClientAuth authentication
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$clientLoginToken = Session::instance('doctrine')->get('google_calendar_client');
 
if ( $clientLoginToken )
{
	require_once 'Zend/Uri/Http.php';
	$client = new Zend_Gdata_HttpClient();
	$client->setClientLoginToken( $clientLoginToken );
}
else
{
	// Create an authenticated HTTP client
	$client = Zend_Gdata_ClientLogin::getHttpClient($this->_guser, $this->_gpassword, $service);
 
	//Cache to DB
	Session::instance('doctrine')->set('google_calendar_client', $client->getClientLoginToken() );
}
 
// Create an instance of the Calendar service
$this->service = new Zend_Gdata_Calendar( $client );