RSS
 
06. Aug. 2012

Namespaces in vendor files and Cake2.x

06 Aug

Have you needed any vendor files (third party libs) that are already written in PHP5.3 and use namespaces? You might find out that they usually don’t work out of the box. The included class is not the problem, but all referenced classes inside this one and its namespace.

I also could not get it to work right away. With some help from tigrang at stackoverflow (namespaces-in-vendor-files-cakephp2-x-and-php5-4-3), though, I could manage to get the class running.

For future reference and for those who stumble upon the same issue here a quick guide.

The namespace loader

Since Cake2.x does not support namespaces yet (3.x then will) we have to write our own loader. You can either put it into your bootstrap or above the class which uses the namespaced vendor lib. I went with the second for now, but the first one would be a more long-term solution.

// PHP5.3 namespace loader for Cake2.x
spl_autoload_register(function ($class) {
    foreach (App::path('Vendor') as $base) {
        $path = $base . str_replace('\\', DS, $class) . '.php';
        if (file_exists($path)) {
            include $path;
        }
    }
});

That’s all you need. Now you can import your vendor file as usual:

// APP/Lib/MyClass.php
App::import('Vendor', 'PackageName', array('file' => 'PackageName/SubFolder/ClassName.php'));
 
class MyClass {
 
    protected $_Engine;
 
    public function __construct($settings) {
        parent::__construct($settings);
 
        if (!class_exists('PackageName\SubFolder\ClassName')) {
            throw new RuntimeException('Your desired vendor library cannot be found');
        }
        $this->_Engine = new PackageName\SubFolder\ClassName($settings);
    }
}

Using classes from the vendor namespace

At some point you might want to use more of the classes in the vendor namespace directly in your cake lib class. You cannot just use say the class “Rule” from “PackageName\SubFolder\SubSubFolder”. You need to prepend the namespace to it:

$newRule = new PackageName\SubFolder\SubSubFolder\Rule($argument);

Same goes for if (class_exists()) {} or similar checks like:

if ($value instanceof PackageName\SubFolder\SubSubFolder\Value\URL) {}

Note: this article is PHP5.3 and above! You can also use this in your 2.x app if you have this minimal php version running (which shouldn’t be a problem nowadays – and with PHP5.4 upcoming already).

It shows that it is possible to use namespaced third party products in your Cake2.x apps.

Namespaces in vendor files and Cake2.x
1 vote, 5.00 avg. rating (96% score)
 
1 Comment

Posted by Mark in CakePHP

 

Tags: , , , ,

Leave a Reply

Tip:
If you need to post a piece of code use {code type=php}...{/code}.
Allowed types are "php", "mysql", "html", "js", "css".

Please do not escape your post (leave all ", <, > and & as they are!). If you have encoded characters and need to reverse ("decode") it, you can do that here!
 

 
  1. Carlos Gant

    June 11, 2013 at 16:09

    You should add a return after the include in the autoload function