the web, technology and miscellaneous rants
Posts tagged Zend Framework
Make your Zend Framework Error Controller handle PHP errors
Dec 3rd
The Zend Framework Quick Start tutorial comes with a great example of the type of error handling Zend Framework can do. Any exception that is thrown almost anywhere in your application is caught and handled by the Error Controller. This allows for very customized development and/or user error messages. But what about generic PHP errors? What about PHP notices? It’s really annoying to see a white screen with a single PHP error after you’ve spent so long trying to get your pretty Error Controller handled errors looking so nice.
PHP has a nifty function called set_error_handler which allows you to, well, set the error handler. You provide it a callback function and it calls your function when something bad happens. While it obviously can’t catch all PHP errors, it does a pretty good job of catching most of the little annoying ones.
Below is a way to set your ErrorController as the PHP error handler.
Add the following method to your Bootstrap.php class.
public function __construct($application) {
parent::__construct($application);
MyApp_Error_Handler::set();
}
Add this code to a file called library/MyApp/Error/Handler.php
class MyApp_Error_Handler {
public static function handle($errno, $errstr, $errfile, $errline)
{
if (!error_reporting()) return;
throw new Exception($errstr . " in $errfile:$errline". $errno);
}
public static function set()
{
set_error_handler(array(__CLASS__, 'handle'));
}
}
Wishing Wagon: Your Online Wish List
Nov 9th
I know I haven’t blogged since August but I have a good excuse. My team and I have been working really hard towards the public beta release of our new online wish list app Wishing Wagon. Basically, Wishing Wagon allows you to create lists of items you would like to receive for a special occasion like Christmas, birthday, wedding, etc. The advantage of Wishing Wagon over other store-based wish lists is that we aren’t store-based. You can add any item you want from any online or physical store.
Since my blog is primarily about technical topics and I’m not sure if promoting my web app can be classified as a miscellaneous rant, I’ll talk a bit about the architecture of Wishing Wagon.
The site was built using PHP and of course my favourite PHP framework, Zend Framework. For the database, instead of MySQL, this time we decided to use Couch DB. I must say that using documents instead of using relational databases feels so much more natural. Documents fit much better with models and I don’t have to worry about Many-to-Many relationships anymore. Couch DB took a bit of time to get used to, but I am now hooked and will try to use Couch whenever eventual consistency is an option.
During the development of Wishing Wagon, I’ve also come to appreciate the built-in Amazon API support in Zend Framework. Retrieving products and searching for items is a breeze. I was a little surprised at how easy it was.
The site is hosted on Rackspace Cloud and is load balanced using HAproxy. We use Rackspace Cloud files as our CDN and we use the Compass Rackspace Cloud Files Zend Framework Library to upload files to the CDN.
I’ll try to blog a bit more about our development experience in the next few weeks.
Don’t forget Christmas is only 45 days away! Why not create a Wishing Wagon and add some items? Oh, and did I mention it’s free?
Accessing CouchDB with Zend Framework using Phly_Couch
Aug 6th
If you have never heard of CouchDB here is the first Paragraph from the Apache CouchDB project documentation: A CouchDB server hosts named databases, which store documents. Each document is uniquely named in the database, and CouchDB provides a RESTful HTTP API for reading and updating (add, edit, delete) database documents.
You can also read the free CouchDB book here.
The easiest way to get started is to sign up for a free CouchDB instance here.
In this tutorial I’m going to show you a quick way of getting CouchDb working with Zend Framework.
I’m assuming you already have a Zend Framework project setup if not get the quickstart here.
Since the Zend Framework doesn’t currently support CouchDB a separate library is required.
Matthew Weier O’Phinney has written a nice library that provides most of the functionality required to work with CouchDB. You can download Phly_Couch here. Once downloaded extract it to your projects library directory.
Add this to your application.ini and modify with your info.
couchDb.host = "username:password@youraccount.couchone.com" couchDb.db = "yourdb" couchDb.port = 80
Add this method to your Bootstrap.php
/**
* Adds configuration to Zend_Registry
* Retrieval example: Zend_Registry::get('config')->couchDb->db
* @return Zend_Config
*/
protected function _initConfig()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
return $config;
}
Use the following code to access your CouchDB instance.
// Establish connection
$couch = new Phly_Couch(Zend_Registry::get('config')->couchDb);
// Create a new document
$testId = uniqid('TEST-',true);
$document = new Phly_Couch_Document($testId);
$document->id = "NewPage";
$document->title = "New Page";
$document->content = "This is a new wiki page!";
$document->created = date('Y-m-d H:i:s');
$document->tags = array('wiki', 'system');
$couch->docSave($document);
// Read Document
$document = $couch->docOpen($testId);
if ($document->getId() != $testId) throw new Exception("ID's do not match. ID=" . $document->getId());
// Delete a document
$document = $couch->docRemove($testId,
array(
'rev' => $document->getRevision()
));
UPDATE:
I had forgotten that I had made some changes to Phly_Couch. I have uploaded the code to Google Code. You can download it here
Creating a JSON-RPC server with Zend Framework
May 20th
For my latest project, I was determined to avoid confusing Ajax requests by implementing my own JSON-RPC. Again, Zend Framework has made this incredibly easy.
The documentation recommends not running your Ajax request through the MVC. At first I was a little concerned, but it makes sense as the MVC does add a lot of unnecessary overhead.
I found this blog very helpful in figuring out how to do this.
The first step is to create a new bootstrap file.
I created one in public/api/1.0/jsonrpc.php
Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../../application'));
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath('../../../library'),
get_include_path(),
)));
/** Zend_Application */
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
$application->getBootstrap()
->bootstrap('doctrine')
->bootstrap('config');
// Instantiate server, etc.
$server = new Zend_Json_Server();
$server->setClass('App_Model_JsonRpc');
if ('GET' == $_SERVER['REQUEST_METHOD']) {
// Indicate the URL endpoint, and the JSON-RPC version used:
$server->setTarget('/api/1.0/jsonrpc.php')
->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
// Grab the SMD
$smd = $server->getServiceMap();
// Return the SMD to the client
header('Content-Type: application/json');
echo $smd;
return;
}
$server->handle();
You may want to modify the $application->getBootstrap() line and add/remove bootstrap methods depending on your requirements. I need access to my database within my JSON-RPC server and use Doctrine as my ORM so I bootstrap that.
The most important line is:
$server->setClass('App_Model_JsonRpc');
This tells the server what class should handle all the JSON requests.
I also added a RedirectRule in my .htaccess file to hide the php extension. It’s unnecessary but the .php extension isn’t seen anywhere else on my site so I don’t want it on my JSON RPC server either.
I added this line…
RewriteRule ^api/([0-9].[0-9])/jsonrpc$ /api/$1/jsonrpc.php [NC,L]
…between these two lines:
RewriteRule ^.*$ - [NC,L] RewriteRule ^api/([0-9].[0-9])/jsonrpc$ /api/$1/jsonrpc.php [NC,L] RewriteRule ^.*$ index.php [NC,L]
I then created a class called App_Model_JsonRpc and put it in my models directory.
/application/models/JsonRpc.php
class App_Model_JsonRpc
{
/**
* Return sum of two variables
*
* @param int $x
* @param int $y
* @return array
*/
public function add($x, $y)
{
return $x + $y;
}
}
The doc blocks are very important as Zend_Json_Server generates the SMD based on the contents of the Doc block.
That’s it for the server. Send it the proper JSON code and it will add 2 numbers together and return the result.
Heres a quick example of how to use your new server.
I recommend installing the ZendJsonRpc jQuery plugin as it makes talking to your server much easier. You can download the plugin here.
<script src="/js/json2.js" type="text/javascript"></script>
<script src="/js/jquery.zend.jsonrpc.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
myApi = jQuery.Zend.jsonrpc({url: '/api/1.0/jsonrpc'});
alert('5+5=' + myApi.add(5,5));
});
</script>
That’s it!
The Importance of Modular Design and Documentation
Mar 24th
I can’t say I learned a lot at school, but I did pick up a few tips that helped me polish up my self-taught coding technique.
During my study of software engineering, my instructors always stressed two things: modular design and documentation. Simple, yet excellent concepts that will save you–and anyone after you–hours and hours of time. I’ve been applying these principles to all of my code ever since I learned about them, but I’ve only recently begun to understand just how important they really are.
I’ve been working with some very unmodularized and undocumented code recently, and I’ve begun to develop an immense dislike for the original author. I’m supposed to add simple little features here and there. By themselves, the features are simple–around 10 to 100 lines each–and would take maybe 10 minutes each to write. To add them to a well-documented, modular coded project might take an hour or two including some testing. But incorporating these tiny features into an existing project base consisting of unmodularized and undocumented code takes 10 to 20 times that. Believe me, I know from experience. I am faced with the constant urge to rewrite the entire code base from scratch. I know it would take longer to rewrite everything, but I have to say it would be much less painful.
Logical code is easy to follow and easy to change. If something is a little strange, then you fall back on the documentation to figure out why. But when the code is an absolute pile of garbage with no documentation, looking like it was written by a first-time coding high schooler, you spend most of your time trying to figure out why the previous author did what they did, how they did it, and why they were ever allowed to touch a computer keyboard in the first place.
The problem increases exponentially when dealing with web projects, especially ones coded in PHP. Modular design in web projects has always been possible but somewhat awkward, considering that up until PHP 5 we had very poor object support. Only in the last few years have there been any decent frameworks to use that employ an MVC structure. My favourite one, of course, is Zend Framework. Before the Zend Framework, I personally had been working on an MVC-like PHP framework of my own to help alleviate the somewhat cumbersome structure that even my PHP projects were sometimes taking. After trying the Zend Framework, I never touched my own framework again.
Having come to realize the power of a good PHP framework and the importance of documentation and modularized code, it just makes me want to cry–and wish horrible things upon the original author whose code is making my job so much more difficult than it should be.