Monday 10 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