[Note: Due to its length, this review has been split up in three. This is Part 1 of a three part review, Part 2 can be found here]
A software framework is a reusable design for a software system (or subsystem) [quote: Wikipedia on Software Framework].
The Zend Framework is a software framework written in PHP and aimed to provide useful and reuseable solutions to (mostly) common web-development issues.
Zend is the company behind the PHP engine, which makes it especially qualified for creating such a framework, all of the developers involved in the Zend Framework project being current/past web-developers with a rich background in the web environment.
While there are many other PHP frameworks available at varying levels of maturity and stability, we chose the Zend Framework for reasons I will elaborate later on. Some of the more prolific PHP frameworks available are CakePHP, Symphony and Prado. For a more comprehensive list, check out this Wikipedia entry and this article on PHPit
Overview of the Zend Framework
The Zend Framework is written entirely in PHP 5 Object Oriented conventions and is currently versioned at 0.9.3 Beta, with a full Release Candidate coming in the immediate future. PHP 5 is a major upgrade over previous incarnations of Object Oriented programming in PHP, and its one of the main reasons I choose the Zend Framework.
The framework is built around modular components that can be used as standalone solutions or in conjunction with other components. In this respect they went to great lengths to make the different components very extendable and portable through the creation of interfaces (another PHP 5 caveat) and making sure the components stay as loosely coupled as possible.
The list of components is quite expansive and diverse - there have been some talk it’s too diverse, and I have to partially agree. However most of the components are useful (to various degrees) and those that aren’t (Re: Zend_Measure. I mean, common) are fairly minor.
The components cover most aspects of web development - Working with databases (Zend_Db and its brethren), authentication and authorization (Zend_Auth and Zend_Acl), dealing with sessions and cookies (Zend_Session and Zend_Http_Cookie), localization and internationalism (Zend_Locale and Zend_Translate), Caching (Zend_Cache), Filtering and Validating (Zend_Filter, Zend_Validate) and many more. Some components implement important software design patterns such as Model-View-Controller artchitecture, the Factory pattern and the Singleton pattern.
A complete list is available on the framework’s website.
I’ll review briefly some of the components that I consider especially useful or interesting:
Zend_Registry - Object/Variable storage container
The Zend_Registry allows the storage and retrieval of objects / variables via a Singleton pattern implementation which persists throughout the web-application.
The Singleton pattern prevents a class from being instanced to a specific object, instead creating a single instance which is stored as a class member. What this means in simpler terms is that you can access a Singleton class from anywhere in your application and be certain you are always using the same object.
The registry is an object oriented alternative to global variables, which are considered evil by most developers. Global values can introduce some security issues, and have the habit of changing or disappearing if you don’t pay close attention to what you are doing. Using the Zend_Registry alleviates those problems, and I’ve been using it heavily in recent web-development projects.
Zend_Db - Database abstraction
Zend_Db, as its name would suggest, is all about working with databases. The entire Zend_Db class hierarchy (Zend_Db, Zend_Db_Adapter, Zend_Db_Profiler, Zend_Db_Select, Zend_Db_Table, Zend_Db_Table_Row and Zend_Db_Table_Rowset) offer various routes for abstraction of database operations.
The base class, Zend_Db, is an implementation of the factory pattern which allows the creation of a database connection adapter without committing to a specific database engine. Currently supported are most of the common SQL RDBMS, including MySQL, MsSQL, PostgreSQL, SQLite, Oracle and IBM DB2. Most of them are accessed through the PDO extension, with special adapters provided for MySQL (MySQLi), DB2 and Oracle in case a framework’s user does not wish to have the PDO extension enabled on his server.
While changing a database engine for a specific web application is not really a common occurrence, different web-development projects could definitely mean working with different databases engines, and for code reusability I consider the Zend_Db factory method very useful. For this reason, combining the Zend_Db factory with the Zend_Registry class is particularly effective - Just instance the Database connection adapter, shove it into the registry and you’re all but protected from possible database engine changes.
The database adapter created by the Zend_Db factory method can be passed on to higher level database abstraction layers such as Zend_Db_Table, or used directly for querying the database. The API provided allows to perform all the basic queries (select, insert, update and delete), allows quoting (to prevent some SQL injection attacks) and is pretty straightforward. The select query was given its own class (Zend_Db_Select) to account for its complexity, and provides methods for most possible query compositions, including Joins, Where and Order clauses, Limit clause (including division of query results into pages - a nice feature), Having and Group clauses and so forth. The only thing missing from my perspective is an abstraction to sub-queries, though admittedly, they are not very common.
Zend_Db_Table - Database table abstraction
In basic Object Oriented software modeling, tables in a database have also class representations that abstract access to those tables. Those classes would usually be called Models in the Model-View-Controller architecture (More on that later on).
Zend_Db_Table is such an abstraction layer for a database table, and implements the Table_Data_Gateway pattern.
What makes the Zend_Db_Table useful is that it simplifies query composition (by predefining table parameters such as table name and primary key) and allows implementation of table relations, enabling many-to-many queries and software based referential integrity such as constraints and cascading operations. This last bit was especially important to me, since I’m not a big fan of setting the referential integrity rules directly in the database (less agile and portable from my viewpoint, and usually incurs additional overhead).
There have been complaints on the lack of a higher level database abstraction class such as the ActiveRecord pattern, and it has become the source of a long and winded debate in the Zend Framework circles. Personally, I do not consider the inclusion of an ORM to be a priority feature in the framework. I am very pleased with using the current Zend_Db_Table class, and extending it with any needed functionality. The Zend development team however are still considering providing an ORM class with the framework and it might be included in future versions.
Next week in Part 2: Model-View-Controller, Zend_Auth, Zend_Session and Zend_Cache