Published 2005-03-18 12:34:41

Someone asked on a few of my other posts why I refer to __autoload as evil, (well apart from making sensationlist statements to keep the blog interesting).

lets start with what it's supposed to get rid of.

require_once 'SomeClass.php';
$x = new SomeClass;

The code above is reasonably predictable, require_once will look in the include path, and find the first match of SomeClass.php, the second line will create an instance of the class that looks like it's probably in SomeClass.php
The only magic here is
  • Which of the include paths SomeClass.php might be in..
Now enter __autoload.
I first saw __autoload on the Zend developers list, it's one of the methods that you looked at and thought, 'is this really a good idea?'. But ignored it, since like all features of any language - 'You dont have to use it'.. or so I thought..

Autoload basically hooks into a few places so when you would normally get a 'this class does not exist' message, autoload is called to let you try and load it, and hence avoid this message.

It also hooks into class_exists(), and gets called to let you try and load the class then, hence the purpose of

class_exists('PEAR') or require_once 'PEAR.php';

On the face of it, the above looks like it is just saving you a file call that require_once isn't really supposed to be doing.. but no.. class_exists is really secret code for 'you can have a go loading the PEAR class from wherever you like'

The justifications I've seen for this are two fold
  • It's better from a performance point of view.
  • It's more flexible.
The first argument, is extremely questionable, the microseconds that you may be saving, compared to parsing all the code that you have in all the classes is probably so tiny as to not be a particular issue. And almost all of it could be removed by using APC or similar if you really where that desperate for performance tweaks.

The Flexibility issue is also questionable, What can you do with autoload that cant be done with include path? or more to the point, what are you doing messing around with include path and autoload locations in the first place.., trying to dig a bigger bug hole for you or someone else to discover later..?

And finally into the fray spl_autoload
Meanwhile as all this was going on, Marcus added an autoloading toolkit to spl, the new 'Standard PHP Library', or perhaps the 'I need more classes library'. What has been added is the missing ability of autoload to be impliemented multiple times.

You can only define one __autoload method per instance of PHP, however spl_autoload allows you to register as many handers as you like, hence multiplying an already magic tool at infinatum. Now you may as well prey that what you typed is actually going to be run as you requested..

Is include_path so complex, troublesome or unflexible that it needs to be replaced with something so much more complex and flexible?

or does somebody want to do something so horrific with __autoload that they are dieing for this tool?

Mentioned By:
google.com : __autoload ( referals)
google.com : php autoload ( referals)
google.com : php __autoload ( referals)
www.nexen.net : Nexen.net : portail PHP et MySQL - __autoload, l'oeuvre du diable? ( referals)
phparch.com : php | architect - The PHP Magazine for PHP Professionals ( referals)
google.com : php autoload performance ( referals)
www.nexen.net : Nexen.net : Portail francais PHP et MySQL ( referals)
google.com : april ( referals)
google.com : march ( referals)
chwang.blogspot.com : Tech Diary: Using __autoload function in PHP 5 ( referals)
google.com : __autoload performance ( referals)
www.phpdeveloper.org : PHPDeveloper.org: PHP News, Views, and Community... ( referals)
google.com : __autoload() ( referals)
google.com : __autoload php ( referals)
www.nexen.net : ( referals)
google.com : december ( referals)
google.com : php __autoload performance ( referals)
google.com : SPL_Autoload ( referals)
www.mail-archive.com : Re: [PHP-DEV] __autoload() enhancement ( referals)
www.planet-php.net : Planet PHP ( referals)

Comments

not evil
Sometimes there is a tendency to include everything an application might possibly need at the beginning whether it will actually get used in that request or not. At least __autoload allows you to lazy load only the stuff you actually do use.

__autoload allows you to map classes and their file locations in one central place. If you scatter file name references to the class all over your application and then decide to change the class location in the filesystem, you have to change multiple files. __autoload allows you to make this type of change in one place for the entire application.
#0 - Jeff Moore ( Link) on 2005-03-18 15:07:45 Delete Comment
what you can do
Well for example you can do some text matches on the class name to determine the directory you want to include from instead of adding many different directories to your include_path.
#1 - Lukas ( Link) on 2005-03-18 15:37:56 Delete Comment
Not so bad
Like everything it could be abused, but at the end of the day it's about communication. If all your developers know full well how classes are included, and the method used is consistent, then why should there be a problem? Document it for new developers/maintainers and everything will be hunky.

Some people say embedding PHP code in templates is evil, but hey they're just damn crazy fools...
#2 - Richard Heyes ( Link) on 2005-03-18 19:21:40 Delete Comment
And...
It also has the potential to enforce a decent naming convention between files and classes.
#3 - Richard Heyes ( Link) on 2005-03-18 19:23:02 Delete Comment
Just a thought
Actually, class_exists() has a second parameter in PHP 5, which removes the 'annoying' autoload behavior. Although maybe you could be so lazy to always type the FALSE... well you can wrap it into another function, like...
ce($class, $autoload=false)
;-)

I'm not sure who is "someone asked on a few of [your] other posts" but sure I'm very thankful to him... :-)

About include_path... it *is* complex. How do you add something to include path without detecting the operating system first? How do you remove something from the include path?
It would be great if PHP has an API that allows manipulation of include paths as array.
#4 - Hendy Irawan ( Link) on 2005-03-18 20:37:44 Delete Comment
better solution?
perhaps a better solution would have been to implement __autoload() as a hook for require/include etc..

At least it would be reacting to a command to load something, rather than catching an error in a weird way..
#5 - Alan Knowles ( Link) on 2005-03-18 21:56:40 Delete Comment
Agreed
Just like what you said about "instanceof" the other day, I can only agree with you again. These 2 pseudo-features are not only useless but will in fact make our developer's life more complicated.

Of course, people won't realize that immediately. It's only when they will want to use other's people code that they will get stuck.

Me wonders who implemented these two in PHP5 ?
#6 - Bertrand Mansion ( Link) on 2005-03-19 00:29:08 Delete Comment
case for class_exists
I think your missing one of the uses for class_exists.

So for customers apps we always include all 3rd party apps within ours. It simplifies management and keeps things from breaking when someone types pear update_all a year down the road.

But that means always having to set the include_path. Now I really would rather not do that, since setting it at runtime can be disabled in the php.ini and now there are more things to go wrong.

I know which PEAR classes im using and its much simpler to include them at the top of the script using a constant and there path within the app. But it doesn't work, even if you've already included the file the pear class will die since its require_once calls won't work.

The only solution i can see for this is
class_exists('PEAR') or require_once 'PEAR.php'

lets people use autoload for PEAR stuff if they want too.
#7 - Joshua Eichorn ( Link) on 2005-03-19 05:30:31 Delete Comment
This is how I use it...
Well, this is how use autoload:

function __autoload($name) {
global $kernelPath; include_once("{$kernelPath}/".strtolower(str_replace("_","/",$name)).".php");
}

So I can simply do $foo=new Foo_Bar; which loads it from my library dir, foo/bar.php. With PHP4 I had to manually do wrapper class and do it like $common->import("foo.bar");

Autoload rocks! :)
#8 - th ( Link) on 2005-03-19 16:52:15 Delete Comment
__autoload is a nice step forward
I see __autoload() mainly as a great step towards improved lazy loading. Its a shame there isn't a complementary method for autoloading functions. Yes, one can query the environment to see if a class/function exists and then provide conditional loading (or more likely, simply use require_once wherever the loaded behaviours are about to be used).

Unfortunately when using larger libraries where one is hoping to JIT behaviours, one can never be sure if the behaviour was already loaded and so one is forced into a pattern of always using require_once before using a class or function.

The problem with that is that it leads to much redundant code splattered throughout. Moreso it requires that two bindings be known and used--the file location and the class/function name--where the latter alone ought be sufficient.

Another point is that when both bindings are required (file and class/function name), the entire library / application becomes more britle as it becomes increasingly difficult to refactor or move files (since they are mentioned in many places including downstream sources). Sometimes this is mitigated by using functions or constants to determine paths but this leads to the same transparency issues and since it is repeated everywhere includes are used, the possibility of frustrating errors and typos are compounded.

Therefore, I see __autoload() as means to help untie class names from physical locations since the latter have no meaning in terms of the application itself. If you have a well defined pattern to name your files and classes, then the idea that one will be unaware of what specifically is loaded becomes somewhat moot. Furthermore, the logic of the loading ought be well-defined in a single place--the __autoload() function and should therefore be easy to decipher.

For me, the only include that should be required in an application is the one that includes the file that defines the __autoload() function itself. After that, I'd rather rely on predictable code to determine file paths and load classes then to leave it to users to continually specify them.

Best Regards.
#9 - boots ( Link) on 2005-04-04 16:52:09 Delete Comment
I hate autoload
That said, I hate includes (in C as well) and requires even more so--Java's imports just disgust me. What I want is an __autoload I can put in one place, will search for a file (regardless of the extension) in whatever directories I choose to insert into a project, and then have an easy way for classes to locate the loader.

#10 - Prez Cannady ( Link) on 2005-09-02 09:15:26 Delete Comment
Force Against Something
Hmm, I've been using __autoload() quite a bit, but decided to look into it a bit more before using it in a larger website (and thus a more important website with money on the line).

After a lot of searching, and using it myself, it seems very few people can find any fault with it. It's a big time saver. Period.

function __autoload($className) {
$classFile = ABSPATH . '/includes/classes/' . strtolower($className) . '.inc.php';
require_once($classFile);
}

And I'm done. I don't need to use any include or require statements anywhere in my code (not for classes anyway), and I don't have to include scripts that might not even get used.
#11 - Sean H ( Link) on 2006-02-22 12:52:19 Delete Comment

Add Your Comment

Follow us on