Monday, July 31. 2006
Okay, it's been a long time, a really long time, since I've posted anything useful on this blog.. Sorry about that, my job at Zend has been keeping me pretty busy and I've been attending a vast number of conferences as well presenting on a whole range of PHP topics...
Although it has been a long time, I thought I would re-enter the blogsphere with a little offering for your playing pleasure. It's something I am calling "ZApp" (standing for "Zend Application", although since I wrote this outside of Zend it's really not my place to use that name). What is it? Well, basically it's an application template built on top of
Zend Framework designed to give the development some organization, tools, and guidance when building an application on top of ZF. I'll admit that I got a number of useful ideas from the
Ruby on Rails folks when I went to implement this but don't let that scare you away -- I think some of their architectual concepts are pretty solid myself, even if overall its too oversimplified/constrained.
For the record, I wrote this pretty much in the last 6 hrs or so for myself. I make no claims you'll like it, find it useful, etc.
Here's a basic rundown of ZApp's features
Automagic (sorta) application generation
One of the things I did think was pretty nice in the ROR system was the ability to automagically generate a whole ton of code. Although cool, I remember back in the day when Microsoft had those MVC application Wizards (do they still?) and thinking to myself how hard it was to figure out what was going on with all this unnecessary crap in the way... So, rather then provide a ROR ./generate counterpart for ZApp what I basically have done is similar to the /ext_skel script in PHP internals. That is to say, there is a ./appgen PHP script which is
very rough at the moment to generate the shell of a new ZF powered application.
Here's how you create a new ZApp for now...
$ tar -zxvf ZApp.tar.gz
$ cp -R ZApp
$ cd
$ php ./appgen
$ chgrp -R nobody webtmp
$ chmod -R 775 webtmp
Assuming you have mod_rewrite installed in Apache, you should now be able to point a DocumentRoot to /www and hit that in your browser... if all goes according to plan, you'll get a little welcome message and can move on with this entry :)
Note: The appgen.php script is very crude at the moment. If this codebase turns into something worth maintaining for others beyond myself I'll probably go back and make a more intelligent installation system
Some ZApp details
Here's some details of how things work...
Basically from a file structure perspective, ZApp comes shipped with everything you need to run the application. It uses the Smarty templating engine for it's MVC View and provides database access via PDO. Eventually ZF itself will provide DB interfaces via an ActiveRecord implementation, but for now PDO is all you have :)
The ZApp directories should look something like this:
include/
controllers/ # ZF Controllers Directory
plugins/ # ZApp plugins Directory
view/ # ZApp_View plugins Directory
views/ # Views (templates) for this ZApp
index/ # Views for the specific controller by name (i.e. this is for IndexController)
APPNAME_DB.php # ZApp Database abstraction
APPNAME_View.php # ZApp View
APPNAME_FrontController.php # ZApp Front Controller
webtmp/ # Temporary storage for ZApp
view_c/ # View (template) compiled files
cache/ # ZApp cache store (not implemented yet)
smarty/ # Smarty distribution
www/ # DOCUMENT_ROOT
index.php # Landing page
.htaccess # Apache Configuration
Zlib/ # Zend Framework Distro
To get started using ZApp you need to know a little about the class structure... here's everything about that...
Base Controllers
There are two base Controllers ZApp provides, ApplicationbaseController and ApplicationController. All ZApp controllers in some way shape or form extend from ApplicationController. The ApplicationController can be modified and provides a location where you can implement "global" Controller Actions which can be found in every controller.
The ApplicationbaseController is a private Controller which takes care of all sorts of things for you such as:
- The automatic rendering of "simple" templates
- Methods to access the view and database objects
- GET(), POST(), COOKIE(), SERVER(), REQUEST(), and ENV() methods which use Zend_InputFilter to filter the respective untrusted data from each source
- Trapping of Bad Route / Bad action calls to provide a consistent user experience
To actually start using ZApp, basically just create two files... Say you wanted to make a http://localhost/foo/ page.. this could be done by simply doing the following:
<?php //FooController.php
require_once 'ApplicationController.php';
class FooController extends ApplicationController {}
?>
{* views/foo/index.tpl *}
Hello, this is the foo Controller!
Of course, if you wanted variables, etc. you can implement specific methods:
<?php //FooController.php
require_once 'ApplicationController.php';
class FooController extends ApplicationController {
public function indexAction() {
if($this->POST()->getRaw('name')) { // Check to see if we have a submission
$this->view()->assign('name', $this->POST()->getAlpha('name'));
}
$this->view()->display('index.tpl');
}
}
?>
{* includes/view/foo/index.tpl *}
{if !empty($name)}
Hello, you entered the name '{$name|ucfirst}' (filtered of course)
{/if}
<form action="/foo/index/" method="post>
Enter a Name: <input type="text" name="name"> <input type="submit" value="Go!">
</form>
Likewise, you can use $this->db() to get your instance of the PDO-powered database connection and do as you please. I personally enjoy this architecture because it has a number of positive traits to it... namely:
- A clear modular separation between the views/code of individual controllers
- An easily used (and easy to audit) filtering system
- A fast deployment into a "working" environment
I have a number of things I'd like to add to this for myself.. feel free to make suggestions but here is my TODO:
- Fix AppGen to be a little more intelligent in the way it does things
- Explore better ways to tie controllers in with segments of the overall view. I.e. for AJAX, where one controller would provide the client with the initial page but other controllers would be responsible only for a subset of that page
- Better error handling, a nice out-of-box default exception handler that is useful
- Caching of data in ZApp where possible (i.e. file_exists() checks) and implementation of a ApplicationController interface to cache data in controllers between requests. I hope to have the ability to cacheusing your choice of PEAR::Cache (or perhaps PEAR::CacheLite), Zend Framework, or APC transparently
- Implementation of a Test Harness probably using PHP_Unit2 and the creation of a skeletion structure for implementing test suites which ties into XDebug (or perhaps an entirely separate bundled extension I'll write) code-coverage tools to measure exactly how good your unit tests are covering your code
- Integration with Zend Framework's PHP Intelligence system for errors which occur at runtime
- Implementation of out-of-box Controller Authentication schemes (i.e. FooController extends MySQLAuthenticatedController) for transparent security / user access in the app
Of course, I'll be implementing these things as I have time (or I need them myself). In the meantime, comments welcome!
Oh, and you can download the ZApp codebase in it's current incarnation right here.