Yii Framework Forum: Getting Yii to play nice with PHP 5.3 namespaces - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Getting Yii to play nice with PHP 5.3 namespaces Rate Topic: -----

#1 User is offline   Marshall 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 11-June 10

Posted 17 July 2010 - 02:36 PM

I have been struggling with using PHP 5.3 namespaces with Yii. The Yii autoloader is passed the namespace AND the class name, so it is not seeing \foo\bar\class as an imported class.

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.
0

#2 User is offline   samdark 

  • Having fun
  • Yii
  • Group: Yii Dev Team
  • Posts: 3,374
  • Joined: 17-January 09
  • Location:Russia

Posted 18 July 2010 - 07:10 AM

What registerAutoloader does is adding another autoloader. What you need is to replace it completely, I think:

spl_autoload_unregister(array('YiiBase','autoload'));
spl_autoload_register($callback);


btw., it will be great if you will share your autoloader along with some usage examples.
Yii 1.1 Application Development Cookbook

Enjoying Yii? Star us at github: 1.1 and 2.0.
0

#3 User is offline   Marshall 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 11-June 10

Posted 18 July 2010 - 07:23 AM

You gave me a new angle to try, since the Yii autoloader loads first sometimes, unregistering should hopefully fix that.

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.
0

#4 User is offline   Marshall 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 11-June 10

Posted 18 July 2010 - 03:20 PM

After poking around some more I came across Symfony's Universal Class Loader which is working great. I am loading and configuring it before I include yii.php and it just works, and Yii's autoloader continues to work well also.

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.

http://github.com/fa...ClassLoader.php
0

#5 User is offline   mindplay 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 397
  • Joined: 03-September 09
  • Location:New York

Posted 27 November 2012 - 03:48 PM

I just spent close to two hours trying everything in creation to get some namespaced classes to autoload. No dice.

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??
0

#6 User is offline   mindplay 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 397
  • Joined: 03-September 09
  • Location:New York

Posted 07 December 2012 - 12:04 PM

Okay, I created my own very simple autoloader - this handles only namespaces (and class-names) that have been explicitly registered with it, so it doesn't replace (or interfere with) the Yii autoloader.

https://gist.github.com/4234540

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.
1

#7 User is offline   rbot 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 8
  • Joined: 30-November 12

Posted 12 December 2012 - 07:52 PM

@mindplay, this is a godsend! Like you I wasted hours trying to import a third-party library that uses extensive namespacing to no avail. Your solution with GAutoloader.php works like a charm. Thank you!

FYI, I used it to import the Balanced Payments library that I had previously posted a forum question about here:

http://www.yiiframew...espaces-in-yii/

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?
0

#8 User is offline   mindplay 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 397
  • Joined: 03-September 09
  • Location:New York

Posted 13 December 2012 - 07:39 AM

View Postrbot, on 12 December 2012 - 07:52 PM, said:

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)?


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.

View Postrbot, on 12 December 2012 - 07:52 PM, said:

Also, the constant YII_PATH is defined in YiiBase.php so how are you using it in yii.php before YiiBase.php is included?


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...)
0

#9 User is offline   lucifurious 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 184
  • Joined: 15-March 09
  • Location:Atlanta, GA.

Posted 15 May 2013 - 02:53 PM

View Postmindplay, on 13 December 2012 - 07:39 AM, said:

You don't need to hack the core - just create your own "yii.php" somewhere outside the code.


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)



0

#10 User is offline   mindplay 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 397
  • Joined: 03-September 09
  • Location:New York

Posted 16 May 2013 - 07:01 AM

View Postlucifurious, on 15 May 2013 - 02:53 PM, said:

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.


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.
0

#11 User is offline   phpguy 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 7
  • Joined: 24-April 11
  • Location:Myrtle Beach, SC

Posted 17 June 2013 - 09:37 AM

It's worth noting that support for autoloading namespaces has been added to YiiBase.php by Qiang in the 1.1.13 release:

- Enh #1481: Added support for autoloading namespaced classes (Qiang)

(change log - http://static.yiifra...ELOG-1.1.13.txt)
Life can only be understood backwards; but it must be lived forwards.
0

#12 User is offline   mindplay 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 397
  • Joined: 03-September 09
  • Location:New York

Posted 17 June 2013 - 06:07 PM

View Postphpguy, on 17 June 2013 - 09:37 AM, said:

It's worth noting that support for autoloading namespaces has been added to YiiBase.php by Qiang in the 1.1.13 release


Actually that was added in 1.1.5, but it never seemed to work for anybody.
0

#13 User is offline   aztech 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 206
  • Joined: 12-December 08
  • Location:Poland

Posted 04 May 2014 - 08:49 AM

I know that the post is very old but maybe it will help somebody.
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.

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'
      ),


Note that:
- $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();

I'm not complete idiot... some parts are missing!
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users