phpzend-frameworkzend-routepsr-4psr-0

How to have "dashes" in filenames in ZendFramework 1.12


I have seen a few posts regarding this question but none were answered to the topic on which they were asked. I have a ZendFramework project (v 1.12) and I want to do some changes in the file naming conventions.

The files and folders are named in Pascal case and I want to make the following changes:

  1. rename all the files/folders to lowercase (this works)
  2. I want dashes ("-") in between words. The Zend maual says that dashes could be there in the file names. But then again says that they should be mapped to the class names, (A Class Name cannot contain a -!!). And now there is Zend Router, it translates the - in URL and joins the words in between them back to the Pascal case. How do I manipulate that?

For example, Here is a file name: TestingDemoController.php, I want to change the name as testing-democontroller.php (actually I was thinking of making it as testing-demo.controller.php but don't know how possible is it.) For the previous filename, the URI used to be something like Testing-Demo. How can the router be configured to not treat - as a special character?

Edit: Questions on PSR:

On the suggestion of @apokryfos, I have been reading through PSR releases, PSR-0 and PSR-4 mostly.

The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.

Is the above point, the only point which I am going against?

Please correct me here if I am understanding it wrong and if am missing something?


Solution

  • I have done this for a project once.

    There are 2 things that need to be done for this to work:

    Override Zend Dispatcher

    In order to override the standard Zend Dispatcher, create a file called Custom.php under "Zend/Controller/Dispatcher" with contents:

    <?php
    
    class Zend_Controller_Dispatcher_Custom extends Zend_Controller_Dispatcher_Standard {
    
        const DELIMITER = '-';
        public function classToFilename($class)
        {
            $class = trim(strtolower(preg_replace('/([A-Z]+)/', self::DELIMITER . "$1", $class)), self::DELIMITER); //str_replace('Controller', '-controller', $class);
            return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
        }
    
    }
    

    and in your Bootstrap.php of your application path, add this function:

    protected function _initControllerDirectoryPath()
        {
                $frontController = Zend_Controller_Front::getInstance();
                $frontController->setDispatcher(new Zend_Controller_Dispatcher_Custom());
        }
    

    This way you will get controllers with a - to be found, eg demo-controller.php. In this case, you will have to change all controllers to the new formats.

    Override module resource loader

    This is tricky, as you need to define your own autoloader. Create a file "MyAutoloader.php" under "Zend/Loader" and add the following code:

    <?php
    class Zend_Loader_MyAutoloader extends Zend_Application_Module_Autoloader {
    
        public function autoload($class)
        {
            $classParts = explode('_', $class);
            $classParts[count($classParts) - 1] = trim(strtolower(preg_replace('/([^_])([A-Z]+)/', "$1-$2", end($classParts))), '-');
            $class = implode('_', $classParts);
            $classPath = $this->getClassPath($class);
            if (false !== $classPath) {
                return include $classPath;
            }
            return false;
        }
    }
    

    and in each module Bootstrap.php, you will need to add:

    class Mymodule_Bootstrap extends Zend_Application_Module_Bootstrap
    {
        public function __construct($application)
        {
            parent::__construct($application);
    
            $r    = new ReflectionClass($this);
            $path = $r->getFileName();
            $this->setResourceLoader(new Zend_Loader_MyAutoloader(array(
                'namespace' => $this->getModuleName(),
                'basePath'  => dirname($path),
            )));
        }
    }
    

    This will enable to use also module resources eg. "modules/mymodulename/forms/search-test.php"

    If you use shared resources, eg forms, models etc, then you also need to register Zend_Loader_MyAutoloader for these in your main Bootstrap by adding:

    protected function _initResourcesDirectoryPath()
    {
        $loader = new Zend_Loader_MyAutoloader(array(
                    'basePath'  => dirname(__FILE__),
                    'namespace' => '',
        ));
    }
    

    Now you can have a file eg forms/test-shared-search.php Note that class names remain the same inside the files(eg Form_TestSharedSearch in the last case)