Tuesday, 11 February 2014

Integrate Zend Framework into CakePHP application

Today, we are going to see how we can integrate Zend Framework version (1.12) into CakePHP Application. In order to achieve this, i created an autoloader script which will load the Zend Framework class at the time of accessing the class (creating object). I used spl_autoload_register() function which will register a function as the __autoload() function. Let's see the autoloader php class implementation.

ZF autoloader class

This  autoloader class  will be named as zf_loader.php contains three static methods which will register an autoloader method into the SPL stack. Following are the three static methods

registerAutoload(): This static method will register an autoloader method with  name 'autoload()' using spl_autoload_register().
autoload($class): This static method will be called, when you are trying to create object for any Zend Framework class. This method will accept class name as parameter.
getPath($class): This static method will return the full file path for any accessed Zend Framework Class.

/**
 * ZF Loader Class for Auto Loading Zend, ZendX Classes
 *  @author Suresh Ariya
 */

/**
 * Loader class that contains register methods for ZendX and Zend classes.
 *
 */

class ZFLoader

{

    /**
     * Autoload function for ZendX and Zend
     * @param $class Class to load
     */

    public static function autoload($class) {

        $file = ZFLoader::getPath($class);
        if(!$file) return false;
        $vendor_file = ZF_DIR_PREFIX . DS.$file;
        require_once $vendor_file;
        return true;

    }


    /**
     * Returns the path for a specific class.
     * Execute the autoloader script only for Zend and ZendX Framework Classes
     */

    public static function getPath($class) {

        $matchFound = false;

       if(strncmp('Zend_', $class, 5) === 0) {
            $matchFound = true;
        } else if(strncmp('ZendX_', $class, 6) === 0) {
            $matchFound = true;
        }

        // convert class name to path

        if($matchFound) {

            $file = str_replace('_', DS, $class).'.php';

            if(!file_exists(ZF_DIR_PREFIX . DS.$file)) return false;

            return $file;

        }

        return false;

    }

    /**
     * "Pre-registers" our autoloader on the SPL stack.
     */

    public static function registerAutoload() {

        $autoload = array(
            'ZFLoader',
            'autoload'

        );

        if(($funcs = spl_autoload_functions()) === false) {
            spl_autoload_register($autoload);
        }

        elseif(function_exists('spl_autoload_unregister')) {

            $buggy = version_compare(PHP_VERSION, '5.2.11', '<');

            $compat = version_compare(PHP_VERSION, '5.1.2', '<=') && version_compare(PHP_VERSION, '5.1.0', '>=');

            foreach($funcs as $func) {

                if($buggy && is_array($func)) {

                    // There are some compatibility issues and some
                    // places where we need to error out

                    $reflector = new ReflectionMethod($func[0], $func[1]);

                    if(!$reflector - > isStatic()) {

                        throw new Exception('
                            autoloader registrar is not compatible
                            with non-static object methods;
                        ');

                    }

                    // Suprisingly, spl_autoload_register supports the
                    // Class::staticMethod callback format, although call_user_func doesn't

                    if($compat) $func = implode('::', $func);

                }

                spl_autoload_unregister($func);

            }

            spl_autoload_register($autoload);

            foreach($funcs as $func) spl_autoload_register($func);

        }

    }

}

loader File

This loader php file will be named as loader.php  will contains the Zend Framework root directory and other configurations, set the root directory path to the set_include_path(). By setting the path in set_include_path(), we are asking PHP to look for the zend framework library files in the included path settings.

Then, we are including the above ZFLoader class (zf_loader.php) using require_once method and calling the registerAutoload() method which present inside the ZFLoader Class. i will be calling the  registerAutoload() method only if you have spl_autoload_register method enabled.
/**
 * autoload files
 * @author Suresh Ariya
 */

$__dir = dirname(__FILE__);

set_include_path($__dir.PATH_SEPARATOR.get_include_path());

// ubm vendor directory prefix constant

if(!defined('ZF_DIR_PREFIX')) {

    define('ZF_DIR_PREFIX', $__dir);

}

if(!defined('DS')) {

    define('DS', DIRECTORY_SEPARATOR);

}

//include the zend framework loader class
require_once 'zf_loader.php';

if(function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {

    // We need unregister for our pre-registering functionality
    ZFLoader::registerAutoload();

    if(function_exists('__autoload')) {

        // ensure that default autoload gets retained
        spl_autoload_register('__autoload');

    }
}
elseif(!function_exists('__autoload')) {

    function __autoload($class) {
        return ZFLoader::autoload($class);
    }
}

CakePHP Controller:

Now we are moving to the main CakePHP Controller class, first we are loading the AppController Class using App::uses(). Next, i am including the loader.php file using App::import() which is similar to the php require_once method.  This method will load the ZF loader.php file present inside the app/Vendor folder.

Here is my CakePHP project folder structure, Both Zend and ZendX library files are present inside the framework folder which is reside inside the app/Vendor folder.

Projectname
    ---- app
             --- Vendor
                       --- framework
                                 --- Zend
                                 --- ZendX
                                 --- loader.php
                                 --- zf_loader.php

Here is the Controller code, inside index() function i am loading the RSS feeds from Google News site using Zend_Feed Class.
App::uses('AppController', 'Controller');

App::import('Vendor', 'zendframework', array('file' = > 'framework'.DS.'loader.php'));

class TestController extends AppController {

    public $uses = false;

    public $helpers = false;

    public $components = false;

    public   function beforeFilter() {

        parent::beforeFilter();

    }



    public function index() {

        $this->layout = false;

        $feed = Zend_Feed::import('http://news.google.com/?output=rss');

        $data = "";

        foreach($feed-> items as $item) {

            $data. = "<p><b>".$item->title()."</b><br />";
            $data. = $item->link()."</p>";

        }

        echo $data;

    }

}

Here is the output RSS feed from Google News.


Hope, you enjoyed this post.

3 comments:

  1. Nice work on this Suresh.. Good Job

    ReplyDelete
  2. Impressive work here, loved the valuable Zend framework information. Thanks for all your efforts.

    Hire RoR Developers

    ReplyDelete