Why Zend Framework Plugins Save You Time

During the recent development of the new PHP cloud development casts site, which has been developed with the Zend Framework, so much development time has been saved by using one of the simplest and arguably best features of the framework: Controller Plugins. So today I want to introduce you to them and walk you through a working plugin so you can see just how effective and efficient they can make your development workflow.


During the recent development of the new PHP cloud development casts site, which has been developed with the Zend Framework, so much development time has been saved by using one of the simplest and arguably best features of the framework: Controller Plugins.

So today I want to introduce you to them and walk you through a working plugin so you can see just how effective and efficient they can make your development workflow.

If you’re not familiar with controller plugins, they’re effectively code snippets that are automatically executed when any one of six events occurs during the Zend Framework application request lifetime. These events are:

  • routeStartup - before the current route is evaluated
  • routeShutdown - after the completion of routing
  • dispatchLoopStartup - before the dispatch loop is entered
  • preDispatch - before the current action is dispatched
  • postDispatch - after the current action is dispatched
  • dispatchLoopShutdown - after the dispatch loop is completed

With these we can intercept the key points in the dispatch process and do some pretty amazing stuff. To get a better understanding of the dispatch process, look at the dispatch process overview diagram below from Thorsten Ruf.

Zend Framework Dispatch Process Overview

Zend Framework Dispatch Process Overview by Thorsten Ruf

What Are They Good For

To give you a taste of what can be done using them, consider the following options:

  • Insert 3rd party account code at the end of every request, such as Google Analytics
  • In a non-production environment, add information to the end of the request body (or page) so that we know, for sure, what environment we’re in and what we’re testing
  • Create a pre-launch or maintenance mode for our application
  • Redirect a user to a specific page if they are or are not logged in

The list really does go on and on. To show you just how simple they are I’m going to show you a controller that was used in the php cloud casts site which managed the redirection to the prelaunch page before the site was live.

  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> MaltBlue_Controller_Action_Plugin_Prelaunch

extends Zend_Controller_Plugin_Abstract

1
2

All controller plugins need to extend Zend_Controller_Plugin_Abstract.

  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span></pre>
  </td>
</tr>
1

We’re going to hook in to the preDispatch event so that we can redirect to the prelaunch page before the current page is loaded, if-needed.

  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #000088;">$auth</span> <span style="color: #339933;">=</span> Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>

if ($auth->hasIdentity()) { return TRUE; }

1
2
3
4

If a user is already logged in, don’t worry about redirecting

  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #000088;">$front</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>

$bootstrap = $front->getParam(‘bootstrap’); $config = new Zend_Config($bootstrap->getOption(‘resources’)); $resource = $request->getModuleName() . ’:’ . $request->getControllerName(); $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper(‘redirector’);

1
2
3
4
5

Get access to certain information about the current environment and load up some configuration details from our application.ini file. The reason the configuration details are in the application.ini file are to avoid having them in code, which makes runtime configuration a lot easier. Below is a sample set configuration which makes the next few snippets make sense.

  <td class="code">
    <pre class="php" style="font-family:monospace;">resources<span style="color: #339933;">.</span>prelaunch<span style="color: #339933;">.</span>launchDate <span style="color: #339933;">=</span> ‘<span style="color: #cc66cc;">2012</span><span style="color: #339933;">-</span><span style="color: #208080;">07</span><span style="color: #339933;">-</span><span style="color: #208080;">03</span> <span style="color:#800080;">09</span><span style="color: #339933;">:</span><span style="color: #208080;">00</span><span style="color: #339933;">:</span><span style="color: #208080;">00</span>’

resources.prelaunch.excluded.routes..name = login resources.prelaunch.excluded.modules..name = administration resources.prelaunch.excluded.modules.1.name = user

1
2
3
4
  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prelaunch</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">excluded</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">modules</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;"></span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>

foreach ($config->prelaunch->excluded->modules as $module) { if ($module->name == $request->getModuleName()) { return TRUE; } } }

1
2
3
4
5
6
7

Even if we’re wanting most of the requests to be redirected to the prelaunch page, we still need to allow content managers to carry out administration of the site. So we check if certain routes have been excluded from being redirected. If so, we allow them to execute as normal.

  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prelaunch</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">excluded</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routes</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;"></span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>

foreach ($config->prelaunch->excluded->routes as $route) { if ($route->name == $front->getRouter()->getCurrentRouteName()) { return TRUE; } } }

1
2
3
4
5
6
7

But as the application’s module based, and there are a number of controllers, which have a number of actions, to list them all is extremely ineffective and is error prone. So we can also exclude entire modules from being redirected, as below.

  <td class="code">
    <pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'prelaunch'</span>

&& $request->getControllerName() == ‘index’ && $request->getActionName() == ‘index’) { return TRUE; } else { $redirector->setCode(303) ->setExit(true) ->gotoSimpleAndExit(‘index’, ‘index’, ‘prelaunch’, array()); }

1
2
3
4
5
6
7

Here we’ve gone through all the exclusions and everything else is to be redirected. So we check if we’re already at the prelaunch page. If so, we simply return true, which completes execution of the plugin.

If not, we set a HTTP code of 303, nice for SEO purposes, indicate that we’re going to exit and then redirect to the index action of the index controller in our prelaunch module, with no supplemental request parameters.

Caveat Emptor (Buyer/Developer Beware)

There is so much more that you can do with controller plugins and this has just scratched the surface. Also, when redirecting in a controller plugin, you need to be careful that you don’t end up in a redirect loop, which I still do from time to time. This can happen based on the logic in your plugin, or if you have a number of plugins and the logic in each isn’t carefully considered.

Nice and Simple.

You can see from this example that we’ve been able to appropriately intercept the relevant segment of the request loop in an elegant and concise way everytime.

We don’t have to re-invent the wheel when building our applications. I hope that this has whet your appetite and that you’ll start using them if you haven’t already.

If you need any further information, check out the Zend Framework manual section on writing plugins and check out an early post that Matthew Weier O’Phinney wrote on them.


You might also be interested in these tutorials too...

Wed, Aug 8, 2012

How to Use the Zend Form ViewScript Decorator In All Modules

If you’ve been using Zend Forms for any length of time, you’ll know just how flexible and configurable they are. There’s not much that you can’t do with them, But it’s not always easy and there are catches. Today we look at ensuring that module-based Zend Forms using the ViewScript decorator can always be initialised no matter what.

Tue, Jun 5, 2012

Zend Form Mastery with Zend Config – Part 4 Configuring Zend Validators

Welcome to the fourth and final part in the Zend Form Mastery with Zend Config series. Previously we looked at the basic form options, element and form wide prefixes, filters and element options. In this installment, we’re going to look at configuring Zend Validators via our XML config.

Fri, Apr 27, 2012

Zend Form Mastery with Zend Config - Part 1 Custom Filter Paths

When you’re working with Zend Form you keep your configuration as much out of code as you can - right? Well, if you’ve been working withZend Form for more than a little while, you know that Zend Config really makes that pretty simple - well, some of the time. In this series we look, comprehensively at how to do it all with Zend_Config.


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus