Admin CMS routes in Zend Framework

Geplaatst in PHP, Webdevelopment, Zend Framework Reeds 10 reacties op dit bericht

For some time now I’ve been pondering on how to implement a CMS in the websites I build using Zend Framework, there are several options available around the internet. Here I’m going to explain how I solved this issue and why this is my preferred way of working.

No custom routing for me sir

One of the solutions I found involved creating a separate module for each part of your website that requires administration (eg: news, blog, products, …). Then you can easily access the admin for each module. For example to access the news admin you would point your browser to domain.com/news/admin.

At this point this solution has one drawback and that is the URL structure, while for some people this doesn’t really pose a problem, I always like to have the part that identifies the CMS as first part of my URL. domain.com/admin/news instead of domain.com/news/admin. You could however solve this by creating some routes, but I still didn’t feel happy about this solution.

While this might be a good solution when you are building a CMS with plug-and-play modules where all code is contained in one module, this solution wasn’t really what I was looking for. I would rather have all my CMS code close together, preferable in a separate environment from my front-end website.

Modules

The solution I found most suited and flexible to use was creating a separate module for both the front-end and the back-end. This allows you to separate your business code from the CMS from your front-end while still being able to use common models for data access and manipulation.

The automatically registered Zend_Controller_Router_Route_Module route takes care of routing the request to the appropriate module or to the default module if no module has been specified.

My directory layout looks something like this.

Admin module directory Layout

You are ofcourse free to use whatever layout works for you, the most important part is that you have at least a frontend and admin module.
You’ll also notice i’ve split up the public directory to separate the public assets for the admin and frontend modules, keeps everything nice and tidy.

Next up is configuring the Front Controller to use modules which is quite easy.

$frontController = Zend_Controller_Front::getInstance();
$frontController->addModuleDirectory(APP_PATH.'/modules');
$frontController->setDefaultModule('frontend');

In the code above we tell the Front Controller where to find the modules and which module to use when none has been specified in the request or when none is found. Pretty basic and it works!
Just put all your CMS specific controllers in the admin module, and all front-end controllers in the frontend module.

But wouldn’t it be nice if we could also separate our Zend_Layout’s, so we have a separate layout for our front-end and admin area’s and the files for these are contained in the respective module directories? This is where Controller plugins come in handy.

/**
 * Controller plugin that sets the correct paths to the Zend_Layout and
 * Zend_Controller_Plugin_errorHandler instances
 *
 * @package    Skyrocket_Plugin
 * @copyright  Copyright (c) 2005-2008 Skyrocket Concepts (http://www.skyrocket.be)
 */
class Skyrocket_Plugin_Adminsetup extends Zend_Controller_Plugin_Abstract
{
	public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
	{
		// Set the layout directory for the loaded module
		$layoutPath = APP_PATH . '/modules/' . $request->getModuleName() . '/layouts/scripts/';
		Zend_Layout::getMvcInstance()->setLayoutPath($layoutPath);

		// Configure the error plugin to use the loaded module
		// so we can use module-specific error handling
		$frontController = Zend_Controller_Front::getInstance();
		$errorPlugin     = $frontController->getPlugin('Zend_Controller_Plugin_ErrorHandler');
		$errorPlugin->setErrorHandlerModule($request->getModuleName());
	}

}

Create a class file like the one above and register the plugin instance with the Front Controller like this:

$frontController->registerPlugin(new Skyrocket_Plugin_Adminsetup());

The Adminsetup plugin intercepts the request before the Front Controller dispatches and modifies the Zend_Layout path to the current module’s Layout directory. It also registers a separate error handler for the admin module in case you want to handle your errors separately from your front-end errors.

What if I still want to use modules for my front-end?

I can hear some of you asking: But what if i’m building a huge website, with a huge amount of business logic? This is what modules really were made for but you are forcing me to use only one module for all my front-end controllers? Does this mean that I should stuff all the code for my forum in one gigantic controller in my frontend module?

No, not really, you still are free to use modules as you please. Feel free to create a forum module with a TopicController, ForumController, PostController and a CategoryController. These modules still work as expected and are accessible via domain.com/forum/topic

Conclusion

See, no funky routing configuration, no numerous admin controllers spead out over dozens of modules, all your admin controllers and layouts are nicely contained within one admin module and you are still able to separate all your code in individual modules or all into one frontend module. The choice is yours.

That’s it for now folks, any remarks, questions or do you think you are using a better method, feel free to comment.


Reacties

  1. 1
    Mon 12 Jan
    butters zei:

    hi, nice article and thanks for sharing this information. this comes in pretty handy right now :)

    10:26
  2. 2
    Wed 25 Mar
    Jason zei:

    Thanks for this post, it helped me immensely!

    17:16
  3. 3
    Sat 02 May
    Corrado zei:

    Hi, nice post, i had same problematics…. but what if I have an admin interface also for the “forum” module? I will have the “forum” module that serves as forntend, but the administration “ForumCotroller” of the “forum” module should be put in the “admin” module in order to have the site.com/admin/forum…. I cannot find a solution for this…

    14:56
  4. 4
    Sat 30 May

    @Corrado Yes, that’s the idea, all your frontend code for the forum goes into the forum module while the administration interface for the Forum is a ForumController in the admin module.

    The basic idea here is to have all your admin controllers together in the admin module

    22:17
  5. 5
    Tue 04 Aug
    kria zei:

    I’m new in zend.
    How route looks like? or can u give show me how bootstrap.php ,public/index.php and application.ini?

    12:20
  6. 6
    Thu 10 Sep
    Marc zei:

    Chris –

    Thanks for the tutorial. I’m having a problem with the custom layout portion and wonder if you have any help.

    I’m using this in my config (ini) file:
    autoloaderNamespaces[] = “Mac_”
    resources.frontController.plugins.Adminsetup = “Mac_Plugin_Adminsetup”

    along with your sample plugin.

    But it appears to be looking for layout.phtml within view/scripts not layouts folder:

    Uncaught exception ‘Zend_View_Exception’ with message ’script ‘layout.phtml’ not found in path (/home/cloozle/private/zend_ots/application//modules/public/views/scripts/:/home/cloozle/private/zend_ots/application//modules/admin/views/scripts/:./views/scripts/

    Any thoughts?

    Thanks!

    08:20
  7. 7
    Thu 22 Oct
    Schio zei:

    Hi, thanks for this post, it’s what I was searching for, separating the business logic keeping the same models. Is there any common/best practice for the admin module among the ZF community ?

    17:28
  8. 8
    Mon 30 Nov
    Max-B zei:

    Can you use Zend Tool command for creating controllers and views for the two modules?

    14:21
  9. 9
    Tue 12 Jan

    Interesting article. Tidy code and works well. Best redards, Jacob (Poland).

    08:57
  10. 10
    Fri 29 Jan

    Hi…

    Nice article, its help me a lot.

    Thanks again,
    Arya

    12:01

Reageer

XHTML: Je mag volgende XHTML tags gebruiken: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>