Archive for the ‘Namespaces’ Category

PHP classes autoload (namespaces) in Zend Framework

Thursday, June 9th, 2011

On previous posts I created a function to dynamically load namespace classes.
Now that I’m using Zend Framework I was wondering how can I use the same namespaces in combination with Zend’s. Following the logic I only needed to register my autoload function so that everything starts working as I wish.
Having read through the documentation I was starting to think it would be very difficult but turned out to be quite simple so I’m posting my learning experience here hoping it would be useful for others.

Background

I have a bunch of namespaces being used for several applications. I have them stored in a specific folder. I use Mac OS.
Let’s suppose I have the namespaces folder located under /var so the namespaces folder path is: /var/namespaces/
Also I have a folder with several non namespaced classes on the following path: /var/classes/

I can’t change paths because several other non ZF applications use that, and I won’t be copying and pasting them into the ZF library path cause if code needs to change I have them all in just one single place.

My ZF application is stored in the following path: /Users/spiro79/web/sites/ZFapp/

ZF must work and be able to load the classes from the different namespaces.

Making it work

I will be using the same logic used in previous posts regarding the autload. Believe it or not is pretty simple.
All changes are done within the bootstrap so open it.
First of all we need to create the autoload function. I wrote this code as a Bootstrap public static function.

    /**
     * Autoload function for PHP namespaces
     * @param string $class
     */
    public static function getMoreNamespaces($class){
        $class = strtolower($class);
        if(strpos($class,'\\')!==false){
            $class = preg_replace('/\\\/',DIRECTORY_SEPARATOR,$class);
        }
        $possibilities = explode(PATH_SEPARATOR, get_include_path());
        $found = false;
        foreach($possibilities as $path){
            if(file_exists($path . DIRECTORY_SEPARATOR . $class . ".php")){
                $found = true;
                require_once $path . DIRECTORY_SEPARATOR . $class . ".php";
                break;
            }
        }
    }

What this code does is that it searches for the namespace folder within all paths set on the include path.
The autoloader will call this function to try to load the namespaces classes.
Now let’s set the namespaces and classes folders in the application.ini file, just add these lines and make them match your own path.

nmspcspth = "/var/namespaces"
clssspth = "/var/classes"

The third and last step is to add my autoload function to the default autoloader. I did this by typing the following code also within the Bootstrap.

    /**
     * Init the autoloader for PHP namespaces
     */
    protected function _initMoreNamespace(){
        $namespacesPath = $this->getOption('nmspcspth');
        $classesPath = $this->getOption('clssspth');
        define('PHP_CLASSES_PATH',$classesPath);
        define('PHP_NAMESPACES_PATH',$namespacesPath);
        set_include_path(get_include_path() . PATH_SEPARATOR . PHP_CLASSES_PATH . PATH_SEPARATOR . PHP_NAMESPACES_PATH);
        $autoloader = Zend_Loader_Autoloader::getInstance();
        $autoloader->unshiftAutoloader(array('Bootstrap','getMoreNamespaces'));
    }

Done! Now you can use natural namespace syntax like:

Use Utils\Config as MyConfig;
$configObj = new MyConfig;
$otherNs = new Utils\Tool();

My problem has been solved and now I can proceed with development 😀