The Zend Framework Bootstrap made simple (Part 3)

Ok, we've established that with the Zend Framework, we need to do a bit more work than some of the other frameworks to get up to speed - but that's not necessarily a bad thing - right?! But it can be a bit tedious and it's something as professional developers, we want to automate away. So we've been addressing in this series how to do just that with a custom, extendable bootstrap class.

In the first part of the series we laid the foundation of our custom bootstrap class by creating a custom class directory structure, adding its namespace to the application ini and modifying the default application bootstrap so that it extends from it and had a look at the first component - caching.

Then, in the second part of the series, we built on the foundation laid in part one by creating plugin resources for the routing table, application navigation and the database connections - these being some of the most common tasks, usually, associated with a web-based application.

In this, the third and final part of the series, I'm going to finish up by looking at application placeholders and surprise, no not logging as originally promised, but pagination. As an added extra, we're going to be using a key feature of Zend Application to make it a breeze.

So with that, let's begin!


So what are placeholders? If you're not familiar with them, the Zend Framework manual describes them this way:

Placeholders allow you to aggregate content, and then render that aggregate content elsewhere.

In short, instead of say, putting raw text for the name of your site or application, your contact email address *or telephone number* throughout your site - creating a nightmare for you (or someone else) to maintain, you create a placeholder, fill it with the desired content, then reference the placeholder throughout your site. Now, when you change the content of the placeholder, you automatically change the content in the rest of your site.

The second benefit of using placeholders, is that they're easier to find (think grep, et al) as they're referred to consistently throughout your application. We can have placeholders for all sorts of content, not just simple text. We can also create sidebars - that change dependent on condition, such as site subsection, user role, seasonal festivals and so on. So how do we create them?

Creating Placeholders

Ok, to make the process a bit simpler, we're going to create a custom resource plugin. How does is this so? Because when we're done all we're going to need to do to create any number of placeholders for our application is to list them with a &'resources.' prefix in our application.ini; where <group> is the placeholder group you want to manage them; think system information, sidebar, promotions etc.

Application Ini Config

Start by adding the following snippet to your application.ini. If you reload the application after you save the file, zend will complain that the plugin's class is not available - so please be patient.

[php] Application placeholders = "My Application" resources.placeholder.application.contactEmail = resources.placeholder.application.url = [/php]

With the snippet above, we're defining three placeholders in a group called application, that's going to be for application wide settings. The settings will contain the name, contact email and url of a fictitious site. Now that that's done, let's have a look at the resource plugin.

Note: Originally I had approached this by just having a broad set of unorganised placeholders, but then, it really seemed to pollute what can be seen as a global placeholder namespace and was a fairly poor design decision - I'm sure you'll agree. So given that I chose to group them together.

Resource Plugin

Here is the class definition for our new placeholder resource plugin class

[php] class MaltBlue_Application_Resource_Placeholder extends Zend_Application_Resource_ResourceAbstract { protected $_placeholders; protected $_view;

public function init() { $this—>_initPlaceholders(); }

protected function _initPlaceholders() { $options = $this->getOptions();

if (!empty($options)) { // ensure view is initialized… $this->getBootstrap()->bootstrap(&'view');

// Get view object: $view = $this->getBootstrap()->getResource(&'view');

foreach ($options as $placeholderName => $placeholderConfig) { foreach ($placeholderConfig as $key => $value) { $view->placeholder($placeholderName)->$key = $value; } } }

return $this->_view; } } [/php]

How does it work?

Given our needs are rather simple, this class doesn't need to be too complex. We create a function _initPlaceholders, which is called in the main init method when our class is loaded.

In the function, we retrieve any options that have been specified for this plugin from the application.ini. If there are any, then we attempt to gain access to the application view resource so that we can create our placeholders. If we're successful in getting access to the view object, we iterate through each group of placeholder directives and create them as specified.

Once we're done, we return the view object, should it be needed later.

Loading the Plugin Resources

Now, all this is fine and dandy, but we haven't made the class available to the bootstrap yet. So, in your application.ini, add the following lines:

[php] ; make the plugin available pluginPaths.MaltBlue_Application_Resource = "MaltBlue/Application/Resource"


Now our new class is available and will be used when the bootstrap encounters the new application directives. You can now reload your application and begin using the placeholders in your application view scripts.

Using placeholders

Ok, what would a good tutorial be, without an example on how to use them. In our default layout view script, add in the following line:


placeholder(&'application')->contactEmail; ?>


Now, when you reload the page, you'll see the email address you specified earlier being output.


I appreciate that I said, in the first part of the series, that it would end with talking about logging, but since writing that, I remembered that logging's all taken care of with the Log resource plugin that ships with Zend Framework. So it seems pointless to rehash it. In light of that, I'm going to end this series by creating a resource plugin and method to initialise pagination with Zend Paginator instead.

As you may know, Zend Paginator is quite a configurable resource. It supports a series of configuration options for such things as:

  • Determining the scrolling type (allelasticjumping and sliding),
  • Setting records displayed per/page
  • Enable caching and
  • Setting a custom view script partial to govern its output

This makes Zend Paginator really flexible and usable in nearly any type of application. Well with the resource plugin and method that follow, we're going to be able to set all of these options just as simply as we configured placeholders. But to do this, we're going to need five things:

  • A resource class
  • A custom route
  • A view script
  • A controller action
  • application.ini configuration directives

So let's have a look at all of the four components mentioned.

The Resource Class

The resource plugin class starts by setting three defaults, one for the scrolling type, one for the records per/page and one for the cache key. As with the placeholder class, we do most of the legwork in a sub-method, in this case _initPaginator, which is called in init() when the class is instantiated.

Also as before, we retrieve any configuration directives specified and then start to use them, or the defaults if none were set for the appropriate values. We start by providing a cache for the paginator, then set the scrolling type, then the records per/page, and finish up by specifying the view partial script to use to display the output.

[php] class MaltBlue_Application_Resource_Paginator extends Zend_Application_Resource_ResourceAbstract { const DEFAULT_SCROLLING_TYPE = &'Sliding';


const PAGINATOR_CACHE = &'paginator';

public function init() { $this->_initPaginator(); } protected function _initPaginator() { $options = $this->getOptions();

if (array_key_exists(&'cache', $options) && $options[&'cache']) { // ensure the cache is initialized… $this->getBootstrap()->bootstrap(&'cachemanager');

// get the cache manager object $manager = $this->getBootstrap()->getResource(&'cachemanager');

// get the paginator cache object $cache = $manager->getCache(self::PAGINATOR_CACHE);

if (!is_null($cache)) { Zend_Paginator::setCache($cache); } }

if (!empty($options[&'scrollingType'])) { Zend_Paginator::setDefaultScrollingStyle( $options[&'scrollingType'] ); } else { Zend_Paginator::setDefaultScrollingStyle( self::DEFAULT_SCROLLING_TYPE ); }

if (!empty($options[&'recordsPerPage'])) { Zend_Paginator::setDefaultItemCountPerPage( $options[&'recordsPerPage'] ); } else { Zend_Paginator::setDefaultItemCountPerPage( self::DEFAULT_RECORDS_PER_PAGE ); }

if (!empty($options[&'viewScript'])) { Zend_View_Helper_PaginationControl::setDefaultViewPartial( $options[&'viewScript'] ); } } [/php]

The controller action

In the controller action, we instantiate our paginator - in this case, from an array that has values from 1 - 50. We then grab the current page number from the route, so that we know where in our list of pages we are and therefore need to display. We pass the current view object to the paginator and set it in the view. Now, we're right to render it in our view script.

[php] $paginator = Zend_Paginator::factory(range(1, 50)); $paginator->setCurrentPageNumber($this->_getParam(&'page', 1)); $paginator->setView($this->view); $this->view->paginator = $paginator; [/php]

The custom route

As we needed to know in the controller action, which page we're on, then it's best to make this as simple as possible with a custom route. The one below does that by specifying a page parameter, which, if not specified, defaults to 1.

[php] ; simple users page routes.users-list.type = "Zend_Controller_Router_Route" routes.users-list.route = users/:page routes.users-list.defaults.module = default routes.users-list.defaults.controller = index routes.users-list.defaults.action = index = 1 = \d+ [/php]

The view script

You can download it here. We don't do much special here. We check if there are any records to display in our paginator and if so, iterate over them. At the end, since we've given the current view object to our paginator and specified the view script partial, all we need to do is finish up by echoing out the paginator and the pagination control is displayed. No more hard work on our part.

The pagination view script partial

The pagination view script partial is taken directly from the search paginator in the zend framework manual. So I'll let it cover it best.

The application directives

Finally, we have the configuration directives. Nice and simple. We have one for all of the defaults previously mentioned.

[php] resources.paginator.cache = true resources.paginator.scrollingType = sliding resources.paginator.recordsPerPage = 10 resources.paginator.viewScript = &'pagination/default_paginator.phtml [/php]

Now, we've done all the leg work required and have simple to use pagination in any of our controller actions. Just four directives along with the accompanying controller action and view script and huzzah - beautiful pagination. What could be simpler?

I apologise for ending differently than initially stated and hope that you don't feel let down by this change of events. As this was such a lengthy set of posts, covering such an important section of the Zend Framework, I'd love to get your feedback in comments and via twitter. So please comment and tweet. Hear from you soon.

Matt's Pic About Matthew Setter

Matthew Setter, a passionate Australian, is the founder and chief-editor of Malt Blue. Follow him on Twitter at @maltblue, join in the discussion on Facebook and find out more about him on the team page.

About Matthew

Matthew Setter Matthew Setter is a PHP & Zend Framework specialist. If you're in need of a custom software application, need to migrate an existing legacy application, or want to know your current application's GPA - get in touch.

Want To Be A Zend Framework Guru?

Drop your email in the box below, and get awesome tutorialsjust like this one — straight to your inbox, PLUS exclusive content only available by email.