Page 1 of 5

Question about autoloading

Posted: Thu May 10, 2007 4:38 pm
by RobertGonzalez
I know autoloading has been posted greatly in this community, and though I think I have some form of understanding in regards to what autoload does, I was hoping someone could clarify for me what autoloading is and how it operates from PHP's perspective. As I understand it, if you use the __autoload() magic function, you can essentially tell PHP that when an object is instantiated to search your filesystem (through the include path setting) for a file to include that will contain the class that you are trying to instantiate. Am I correct in this assessment?

Also, with the advent of the SPL and the spl_autoload_register() function, does that mean that you would not have to use __autoload if you use spl_autoload_register()? If so, what does the function do natively that would normally be expected in a user defined __autoload() function?

I apologize for newbiness in this arena. I have searched these boards and Google'd the crap out of the topic. I just really am interested if there is a benefit to using it and, if there is a benefit, then is there a proper means by which to use it? Thanks in advance for any help you might be able to offer.

Posted: Thu May 10, 2007 5:11 pm
by Luke
In the simplest of terms, __autoload is called whenever an instance of a class is instantiated and php knows of no such class. The __autoload function does absolutely nothing (as far as I know) until you define it. So, the simplest method of doing so is just to do something like:

Code: Select all

function __autoload($classname)
{
    if (!class_exists($classname))
    {
        $path = str_replace('_', '/', $classname);

        if (file_exists($path)
        {
            require_once $path;
        }
    }
}
Now, this particular function is pretty useless since it has no way of searching your include path for file_exists(). That's what the classes I sent you do. This is probably a pretty bad explanation as well, but it's the best I can do :)

Another option is to define a specific lib path in a (ugly) constant and be sure to put all of your includes within that path:

Code: Select all

define('CLASS_PATH', '/lib/');

function __autoload($classname)
{
    if (!class_exists($classname))
    {
        $path = str_replace('_', '/', $classname);

        if (file_exists(CLASS_PATH . $path)
        {
            require_once $path;
        }
    }
}
Oh and you're such a newb :wink: :lol:

Posted: Thu May 10, 2007 5:14 pm
by Christopher
The thing about these PHP5 "__" functions is that many of them are error handlers and not actually language or library level solutions to things like class loading. Some may say they are smart solutions; I say they are symptoms of poor language design due to lack of knowledge and vision.

Be that as it may, the autoload functions are not "magic functions that search your filesystem for a file for that class." The are simply error callback functions for the new keyword. If there is a "class not found" error when a new is executed, then a callback will be called if it exists. At that point it is up to you what that function does and there are various schemes for loading the correct file ... usually based on the class name (which is passed to autoload).

Posted: Thu May 10, 2007 5:22 pm
by RobertGonzalez
So does the spl_autoload_register() function have a dependency on __autoload()? Also, what is the benefit of autoloading? I only ask because I have seen others' comments about doing away with the scroll of include and require statements in library files for their frameworks because of the use of autoloading. Is that just a cheap way out of doing things the right way (like using error suppression when fixing the error is actually an option)?

Posted: Thu May 10, 2007 5:30 pm
by Christopher
spl_autoload_register() uses the same internals but allows multiple callbacks because there is on one __autoload(). A super solution to a super design -- two ways to do something important not very well.

autoload is was a cheap language solution, but it is not necessarily a cheap application solution. It really depends on your framework as to whether it make specific things cleaner or solves specific problems.

Posted: Thu May 10, 2007 5:39 pm
by RobertGonzalez
arborint wrote:Be that as it may, the autoload functions are not "magic functions that search your filesystem for a file for that class." The are simply error callback functions for the new keyword. If there is a "class not found" error when a new is executed, then a callback will be called if it exists. At that point it is up to you what that function does and there are various schemes for loading the correct file ... usually based on the class name (which is passed to autoload).
Ok, now for more questionings...

I recently saw in someone's framework code a call to spl_autoload_register() in which a static public method was passed to the function. How does that jive with error handling functionality in conjunction with the new keyword since static methods are essentially class functions rather than object methods? I am not totally seeing the benefit of this yet, so I am asking so I can get a decent grasp of what this concept offers.

Posted: Thu May 10, 2007 6:42 pm
by Christopher
It does not really matter what the callback function is -- a plain function, a static class function or a object method. It takes the same argument as call_user_func().

Posted: Thu May 10, 2007 10:45 pm
by Kieran Huggins
There has always been some debate about the usefulness of __autoload(). I use it personally, it helps save memory and cuts down on the redundant code bulk of including_once each class file before you use it. It's a shortcut, and I'm alright with that.

Like any other function you should always know when, where and why it's being called. If you have those bases covered, you're good to go.

As an example, say you have all your classes in separate files like so:

classOne is in /classes/classOne/index.php
classTwo is in /classes/classTwo/index.php

then your __autoload() would be:

Code: Select all

function __autoload($classname){
   require_once('/classes/'.$classname.'/index.php');
}
easy-peasy.

Posted: Fri May 11, 2007 2:59 am
by Maugrim_The_Reaper
There has always been some debate about the usefulness of __autoload(). I use it personally, it helps save memory and cuts down on the redundant code bulk of including_once each class file before you use it. It's a shortcut, and I'm alright with that.
Does it save memory? I understand it's basically a form of Lazy Loading, but most classes will already have require_once statements for any other class they need somewhere close to hand - so autoloading can't be much more lazy than that. It should also be qualified - saving memory may not be all that beneficial in comparison to the benefits of an in-memory opcode cache. So whether autoload has any performance benefits is debatable.

Posted: Fri May 11, 2007 3:37 am
by Kieran Huggins
when I said "saves memory" what I meant was it saves memory over the alternative of loading every class regardless of whether they're used or not. I could be wrong, PHP may do some smart-ass-opcode-cache-separation-kejigger.

Is there a downside to using __autoload() ?

Posted: Fri May 11, 2007 4:13 am
by wei
beware that if you call class_exists($className) without the optional 2nd argument will trigger the __autoload to be called. If you want to prevent the autoload, you need: class_exists($className,false)

lots of fun ;)

Posted: Fri May 11, 2007 5:09 am
by Maugrim_The_Reaper
Probably a design issue - In my own libraries each class just makes a require_once call for any classes it needs. I rarely see applications loading up everything even if it's not needed. If that were the case, __autoload would save memory where an opcode cache was not available. Where an opcode cache is installed (like APC), any loaded class will just get cached in memory for the next time. As a plus since it was a pain in the ass, require_once is quite a bit faster as of PHP5.2 - that always worried me more than anything else...;).

Downside to __autoload? None as such. A year ago I'd have pointed out that __autoload and opcode caches didn't play together, but that has been resolved since (esp. in APC). There is a small performance hit since opcode caches now cache the actual file (knocking out the i/o op) but still can't cache it's parsed classes and methods. Usually though it's a tiny difference - the file operation is more expensive by far usually.

Personally I stick with require_once. If I want __autoload I'll use the SPL registry (safer than using __autoload when embedded applications could already have defined it) and likely use a Phing task to strip out the require_once calls. So I can move between both worlds with little more than a command line parameter ;).

Posted: Fri May 11, 2007 5:14 am
by Jenk
__autoload is only invoked once per unique classname - providing of course you define the class required (either by including/requiring or by dynamically defining) so there really is no difference as you will be including the class file anyway, at which point the usual opcode cache takes place.

The difference between including/requiring manually just in case you need it, and letting __autoload() do it for you when and if you need it is utterly negligible.

Posted: Fri May 11, 2007 5:27 am
by kyberfabrikken
The Ninja Space Goat wrote:

Code: Select all

function __autoload($classname)
{
    if (!class_exists($classname))
    {
(...)
Calling class_exists() inside __autoload makes little sense. If anything, it should be class_exists($classname, FALSE), but it's still completely redundant.
Kieran Huggins wrote:when I said "saves memory" what I meant was it saves memory over the alternative of loading every class regardless of whether they're used or not. I could be wrong, PHP may do some smart-ass-opcode-cache-separation-kejigger.

Is there a downside to using __autoload() ?
Appearently, there are some problems with autoload vs. opcode caches. I haven't had time to investigate it in details, but according to this post, using autoload, makes it impossible for apc to cache the file.

Posted: Fri May 11, 2007 5:39 am
by Oren
No, class_exists() shouldn't be there at all. __autoload() is called only when you are trying to use a class which hasn't been defined yet.