Raza Mehdi's Blog

Get list of all modules with all controllers and actions in Zend Framework

by on Jan.06, 2011, under Zend Framework

Hi guys!

Finally back after a long time. I have been really busy at work.  In one of the projects, i had to get list of modules plus controllers and their respective actions for ACL configuration purposes .. I implemented the said task using action helper and controller plugin in Zend Framework. I am listing the Action helper code here. Also, when done with ACL, i will post that code here as well …

Before getting started, i am going to assume that you have configured Zend Framework installation on your local machine and setup your application through a virtual host.

First, open the Bootstrap.php in your application directory and put the following code:

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

    protected function _initAutoLoad(){
        $autoLoader = Zend_Loader_Autoloader::getInstance();
        $autoLoader->registerNamespace('Application_');

        return $autoLoader;
    }

    protected function _initActionHelpers() {
        Zend_Controller_Action_HelperBroker::addHelper(new Application_Action_Helper_AssetsList());
    }

Now do the following:

  1. Create a folder called Application in your site’s library folder.
  2. Then create sub-folder called Actionin the Applicationfolder.
  3. Again create a sub-folder called Helperin the Actionfolder.
  4. Now a create a file called AssetsList.phpin the plugin folder.

In the AssetsList.php folder, write the following code:

<?php
class Application_Action_Helper_AssetsList extends Zend_Controller_Action_Helper_Abstract {

    public function  direct() {
    }

    public function getList() {
        $module_dir = $this->getFrontController()->getControllerDirectory();
        $resources = array();

        foreach($module_dir as $dir=>$dirpath) {
            $diritem = new DirectoryIterator($dirpath);
            foreach($diritem as $item) {
                if($item->isFile()) {
                    if(strstr($item->getFilename(),'Controller.php')!=FALSE) {
                        include_once $dirpath.'/'.$item->getFilename();
                    }
                }
            }

            foreach(get_declared_classes() as $class){
                if(is_subclass_of($class, 'Zend_Controller_Action')) {
                    $functions = array();

                    foreach(get_class_methods($class) as $method) {
                        if(strstr($method, 'Action')!=false) {
                            array_push($functions,substr($method,0,strpos($method,"Action")));
                        }
                    }
                    $c = strtolower(substr($class,0,strpos($class,"Controller")));
                    $resources[$dir][$c] = $functions;
                }
            }
        }
        return $resources;
    }
}

To get the list, simply put the following line in any controller action:

$resources = $this->_helper->AssetsList->getList();

Hopefully, this helps out everyone. I will post the dynamic ACL plugin code in coming days when i am finished with it.

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks

  • max4ever
  • http://Problemaboutit, Dr.SoFtNaF

    Hello Raza,

    Thank you for your code above, but it seems it have a problem, when you execute it, you don’t get the modules, controllers and actions, but you get the modules, and all controllers exists in the application which extends from Zend_Controller_Action and it push it into the $dir loop.
    The result looks like that:
    Default
    Index
    Error
    Article_Index
    Auth
    StaticContent
    Admin_Index
    Admin
    Articles.
    I have made some changes in your code above to:

    public function getList() {
    $module_dir = $this->getFrontController()->getControllerDirectory();
    $resources = array();
    foreach ($module_dir as $dir => $dirpath) {
    $diritem = new DirectoryIterator($dirpath);
    foreach ($diritem as $item) {
    if ($item->isFile()) {
    if (strstr($item->getFilename(), ‘Controller.php’) != FALSE) {
    $classPath = $dirpath . ‘/’ . $item->getFilename();
    include_once $classPath;
    $php_file = file_get_contents($classPath);
    $tokens = token_get_all($php_file);

    $class_token = false;
    foreach ($tokens as $token) {
    if (is_array($token)) {
    if ($token[0] == T_CLASS) {
    $class_token = true;
    } else if ($class_token && $token[0] == T_STRING) {
    $class = $token[1];
    if (is_subclass_of($class, ‘Zend_Controller_Action’)) {
    $functions = array();
    $c = strtolower(substr($class, 0, strpos($class, “Controller”)));
    foreach (get_class_methods($class) as $method) {
    if (strstr($method, ‘Action’) != false) {
    $resources[$dir][$c][] = substr($method,0,strpos($method,”Action”));
    }
    }

    }
    $class_token = false;
    }
    }
    }
    }
    }
    }
    }
    return $resources;
    }

    and I got the correct result as:
    Default
    Index
    Error
    Auth
    Admin
    Admin_Index
    Articles
    Article_Index

    I am Working as well on matching the Zend_Acl with Modules, Controllers and Actions.

    Kinds regards

  • Raza

    Hey!

    Thanks for your comment. The code that i wrote in my post simply outputs the modules, controllers and actions in a array format like this:

    array(
    ‘module 1′ => array(
    ‘controller 1′ = array(
    ‘action 1′,’action 2′,…..,’action n’
    ),
    ‘controller 2′ = array(
    ‘action 1′,’action 2′,…..,’action n’
    ),
    ),
    ‘module 2′ => array(
    ‘controller 1′ = array(
    ‘action 1′,’action 2′,…..,’action n’
    ),
    ‘controller 2′ = array(
    ‘action 1′,’action 2′,…..,’action n’
    ),
    ),
    );

    Your solution is also interesting. I will definitely implement it to see whether it works better than my solution.

  • http://www.geekpub.de Arne Riemann

    Thanks for your article, iam sure i will need it in future ;-)

  • http://twitter.com/Tzonev Martin Tzonev

    Very useful code, just one tiny bit to add. With the code used as it is with modular structure (the default module plus another one) I got the module I called the method from twice (along with its methods). Fixed it by moving the loop of the declared classes (second foreach) outside the modular loop. Works like a charm regardless of where you call it from.

    Thank you!

  • http://www.facebook.com/vitorgabriel11 Gabriel Vítor de Sousa

    Thansk Brother! It’s very useful.

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!