Tag Archives: Mvc

Setting up a maintenance page with Zend Framework

One of the things that smaller sites who don't have a fully redundant setup or a relatively minimal deployment mechanism need to do when doing some kind of maintenance is put up an "Under Maintenance" page.  That or there was some massive problem and you need to just shut down access to the site while you fix the problem.  With that in mind I have written a very simple example that allows you to create a maintenance page that is configurable and requires no changes to your existing site.  This example uses Zend_Application, but all of the code can be used in a pure Zend_Controller application by adding the plugin however you normally add plugins.

First let's set up a maintenance controller.

MaintenanceController.php

class MaintenanceController extends Zend_Controller_Action
{
    public function indexAction(){} 
}

and a view.

scripts/maintenance/index.phtml

<h1> We are currently under maintenance</h1>

<h2> Please check back soon</h2>

Now the fun part.  Create a simple plugin that is called during routeShutdown() and redirect all requests to the maintenance page.

class Esc_Application_Plugin_Maintenance extends Zend_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        $request->setActionName('index');
        $request->setModuleName('default');
        $request->setControllerName('maintenance');
    } 
}

One of the nice things about this method is that if you have any parts of your application that you want to keep open you can implement the code to handle that in here.

The last thing you need to do is add this plugin to your application configuration.  If you are using Zend_Config_Ini you can simply do this:

resources.frontController.plugins[] = "Esc_Application_Plugin_Maintenance"

Whenever you need to put your site into maintenance mode all you need to do is add that line and it will be done as soon as you save the file.

Friday Framework Highlight: Zend Framework MVC Request Lifecycle

Dispatch loop

Matthew wrote up an article on modules in Zend_Application and that got me thinking a little bit.  When I have done training for Zend Framework, one of the things that mystifies students to some extent is the whole plugin architecture and where things can go.  There has been several articles written about it, but they tend to use code to describe it.  I was only able to find a small handfull of articles that used some kind of chart to describe what goes on.  Not that that's a problem, but I had found that when I drew out the request lifecycle that it helped the students understand it better.

The chart on the right is a color-coded chart that shows when something is executed and where it is executed from.  This chart is intentionally missing a whole bunch of things for the purpose of simplicity.  If you want a more full explanation of the request lifecycle here is a great PDF that might help.  For an introduction to plugins (with code examples but no diagrams :-) ) go here.

Note: to have a plugin potentially execute in all of the hooks you will need to add it in your bootstrap file, or class, prior to the front controller calling its dispatch() method.

The first hook that is run is the routeStartup().  It is run one time prior to the route being decided.  If you have any kinds of custom routing that needs to be done, this might be the place to do it.

The second hook is the routeShutdown() hook.  If you have module/controller/action based access control, this is not a bad place to put it.  It is the very first time that you will know what the module, controller and action will be.  That way if someone tries to access a certain URL that they shouldn't have access to they will be stopped immediately.  However, if you use a lot of forwards or if you use the action stack a lot to hop around between controllers, modules and actions then this would not be a good place for access control since it is only called once.  The error handler uses the routeShutdown() hook to check if it is handling an error for the current dispatch loop iteration so it can forward the dispatcher to the error controller prior to any other logic being called.

The next hook is the dispatchLoopStartup() hook.  This is called immediately before the dispatch loop is started, and right after routeShutdown().  Functionally, at this point in time, there is no difference between dispatchLoopStartup() and route

After dispatchLoopStartup() is called, we enter the dispatch loop which is handled within a do-while statement, so it will run at least once.  The next hook to run is the plugin preDispatch().  This method will be executed for each and every dispatch loop that runs.  If you have a lot of forwards or use the action stack a lot to cross access control lines, this is a good place to put that control, instead of in routeShutdown() or dispatchLoopStartup().

After that, the execution moves to the dispatcher.  This is where the controller class is loaded and instantiated.  Because this is where the controller is instantiated, it is also where the controller init() method is called.  A new controller object will be created for each and every dispatch loop, whether or not it is iterating over the same controller name.  Therefore, init() will be called once per dispatch loop.

After the controller has been instantiated we move from the dispatcher's dispatch() method into the controller's dispatch() method.  The first thing that happens is that the controller dispatch calls all of the controller helper's preDispatch() method.  The preDispatch() method will only be called if the helper has been either a) referenced, or b) explicitly instantiated.  Therefore, the preDispatch() method in a controller action helper MAY be called.  In a plugin, the preDispatch() method WILL be called.

Once the controller action helper preDispatch() method has been called the controller's individual preDispatch() method is called.  This is used to implement any functionality that is universal to the individual controller.  Setting up contexts is an example of what you can do here.

Then the individual action is called.  This, of course, is where you implement your logic for the individual piece of functionality that this required for this specific module, controller and action combo.

After that, the postDispatch() method is called on the controller.  This is where the View Renderer is called.  If you need to do something either immediately before or immediately after the View Renderer, this is a good place to do it.

The last point of execution for the individual dispatch is the plugin postDispatch().  An example of what is executed here is the Zend_Layout plugin.  This call is handled in the front controller.

Here, the front controller has a decision to make.  It will check to see if there are any outstanding actions to be executed.  If so, it will start the do-while loop over again.  If not, it will exit the loop and call the dispatchLoopShutdown() method on all of the plugins.  In Zend Framework 1.10 there is only one component that uses this, and that is the Wildfire component.

So that is a brief overview of the request lifecycle in Zend Framework MVC applications.  There's nothing new or special here, except that this posting has a picture with funny colors.