Getting Yii to play nice with PHP 5.3 namespaces
Posted 17 July 2010 - 02:36 PM
I have tried creating my own autoloader and registered it using Yii::registerAutoloader(), but for some reason the Yii autoloader is running first some of the time.
If anyone has solved the problem, or knows of a strategy that works, I would appreciate it if you would share it with me.
Posted 18 July 2010 - 07:10 AM
btw., it will be great if you will share your autoloader along with some usage examples.
Posted 18 July 2010 - 07:23 AM
I will write my own autoloader that detects namespaces and loads them, otherwise it will call the Yii::autoload() explicitly instead of letting SPL fall through.
I will post the results of my tests, with code.
Posted 18 July 2010 - 03:20 PM
This more advanced autoloader looks so simple, it would be great if Yii had something like it for those of us that use PHP 5.3 and/or components from more than one framework. (Yii is my core framework, but I am a hardcore DRY guy.)
Here is what Symfony's autoloader looks like if anyone wants to use it or port it.
Posted 27 November 2012 - 03:48 PM
My classes are in two-level namespaces, e.g. "vendor\package\Class", standard PSR-2 conventions - I cannot for the life of me get these to autoload.
The documentation on this subject is shifty - 3 paragraphs talking about how to autoload "application\components\GoogleMap", but then the example shown at the end of that whole discussion is a simple 1-level namespace. And yes, that works - I can map a root-level namespace to a folder and get that to autoload. But I have two packages from the same vendor, so that's not good enough.
Has this problem not been addressed in later versions of Yii?
Do I really have to circumvent Yii's autoloader and pull in the one from Zend or Symfony like I've seen it explained in various blog posts??
Posted 07 December 2012 - 12:04 PM
I find it astounding that Yii to this day still doesn't have an actual autoloader - a class you can extend.
Bottom line is, using namespaces with Yii is painful and takes WAY too much work - this is an ordinary, basic requirement for any developer these days, nearly all modern third-party packages use namespaces by now.
This should not require any work or thought at all, and certainly should not involve pulling third-party packages from other frameworks.
What. The. Hell.
Posted 12 December 2012 - 07:52 PM
FYI, I used it to import the Balanced Payments library that I had previously posted a forum question about here:
Just to clarify, your custom yii.php file goes in the core yii dir (not docroot) and replaces the standard yii.php file that docroot/index.php includes right? Is there a "pure" solution that doesn't involve hacking core (if not, I can certainly live with this)? Also, the constant YII_PATH is defined in YiiBase.php so how are you using it in yii.php before YiiBase.php is included?
Posted 13 December 2012 - 07:39 AM
You don't need to hack the core - just create your own "yii.php" somewhere outside the code. If you look at the standard Yii class, it's just an empty class that extends YiiBase. It's designed this way, so that you can extend YiiBase with your own Yii class, which enables you to add or override methods in the static Yii class.
So you don't need to hack any of the files in the actual Yii codebase, just ignore the standard Yii-class and load your own instead.
That's an artifact of the way I set up my own Yii apps, you can substitute that as needed. (I have a separate environment setup, configuration and bootstrapping system that loads before Yii does...)
Posted 15 May 2013 - 02:53 PM
I went down this path... Unfortunately because of the poorly coded YiiBase.php (i.e. use of self:: and Yii:: instead of static: no overridden methods ever get called.
My solution was to just to yank the Yii autoloader completely and use the composer one. I've almost got it working and will share my results.
I'm having issues now where the autoloader is trying to prefix a namespace to global PHP classes used inside Yii (i.e. \Iterator in CListIterator)
Posted 16 May 2013 - 07:01 AM
I agree, it's not sound, but late static binding was only introduced in PHP 5.3, Yii still targets PHP 5.1, and unfortunately has not gotten the maintenance it should have since it's initial release.
Having made the (also questionable) design choice of using a static class, they did the best they could under the circumstances, which was to have this vestigial Yii-class in place, so that at least you can override certain methods by loading a different implementation of that class.
For most common purposes, such as overriding createWebApplication(), it doesn't cause any problems, because no code ever calls YiiBase::anything() - all calls are made to Yii::something() which by default will bubble up to the YiiBase parent class, unless you provide your own implementation. But yes, any method that references self::something() (or worse, static private variables) from inside the YiiBase class, will have to be completely replaced (cut and paste!) if you want to "override" the default implementation.
The solution I posted does work - I'm using it in production on two different sites by now.
Posted 17 June 2013 - 09:37 AM
- Enh #1481: Added support for autoloading namespaced classes (Qiang)
(change log - http://static.yiifra...ELOG-1.1.13.txt)
Posted 17 June 2013 - 06:07 PM
Actually that was added in 1.1.5, but it never seemed to work for anybody.
Posted 04 May 2014 - 08:49 AM
There is no need for write any complicated autoloaders. Yii has support for namespaced classes but it is well hidden
The solution is described here: http://shiki.me/blog...-yii-framework/
Personally I prefer a mixture of above solution with Yii application configuration. I'm going to explain it basing on example.
I would like to add Complexify class (https://github.com/m...php-complexify/) which is using namespace Complexify.
The first step is to update aliases parameter of the application in the configuration file to register Complexify alias and point it to a directory where our namespaced class is:
'aliases' => array( 'common' => $root . DIRECTORY_SEPARATOR . 'common', 'Complexify' => $root . DIRECTORY_SEPARATOR . 'common' . DIRECTORY_SEPARATOR . 'extensions' . DIRECTORY_SEPARATOR . 'complexify' ),
- $root points to my root directory
- aliasses do not point the class ifself but only the folder where the namespaced class is stored;
Now I can create the class using namespace:
$check = new \Complexify\Complexify();