12

PHP's __autoload() (documentation) is pretty interesting to me. Here's how it works:

  • You try to use a class, like new Toast_Mitten()(footnote1)
  • The class hasn't been loaded into memory. PHP pulls back its fist to sock you with an error.
  • It pauses. "Wait," it says. "There's an __autoload() function defined." It runs it.
  • In that function, you have somehow mapped the string Toast_Mitten to classes/toast_mitten.php and told it to require that file. It does.
  • Now the class is in memory and your program keeps running.

Memory benefit: you only load the classes you need. Terseness benefit: you can stop including so many files everywhere and just include your autoloader.

Things get particularly interesting if

1) Your __autoload() has an automatic way of determining the file path and name from the class name. For instance, maybe all your classes are in classes/ and Toast_Mitten will be in classes/toast_mitten.php. Or maybe you name classes like Animal_Mammal_Weasel, which will be in classes/animal/mammal/animal_mammal_weasel.php.

2) You use a factory method to get instances of your class.

$Mitten = Mitten::factory('toast');

The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"

Therefore, you can start out using a generic mitten throughout your code, and when the day comes that you need special behavior for toast, you just create that class and bam! - your code is using it.

My question is twofold:

  • (Fact) Do other languages have similar constructs? I see that Ruby has an autoload, but it seems that you have to specify in a given script which classes you expect to use it on.
  • (Opinion) Is this too magical? If your favorite language doesn't do this, do you think, "hey nifty, we should have that" or "man I'm glad Language X isn't that sloppy?"

1 My apologies to non-native English speakers. This is a small joke. There is no such thing as a "toast mitten," as far as I know. If there were, it would be a mitten for picking up hot toast. Perhaps you have toast mittens in your own country?

Nathan Long
  • 122,748
  • 97
  • 336
  • 451
  • 1
    love using this, especially when working with less experienced developers ... "why is this working, where are the includes/require" etc. – Hannes Oct 19 '10 at 09:28
  • 2
    @Hannes - isn't "it confuses newbie developers" a reason **not** to like it? – Nathan Long Oct 19 '10 at 09:33
  • I'd read right through your description of autoload before I found the comment about small joke. Until that point, I'd been reading Toast_Kitten rather than Toast_Mitten... left me with a different image in my mind. Personally, I find autoload extremely useful, especially in memory hungry applications, but it's sloppy enough to cause problems if you have multiple third-party libraries each of which uses its own autoloader (developers don't always remember to register their aotoloaders correctly in this case, then complain that the libraries don't work) See Gordon's comment for the solution – Mark Baker Oct 19 '10 at 09:34
  • 1
    @Nathan Long we grew with our Challenges, i see myself as a mean Mr. Miyagi, nah all kidding aside, its a great concept but it can also quite confuse you if you are not familiar with it. Furthermore if you apply your own logic here one should try to use it in a Way that makes sense ... for example `class Category_Package_Subpackage_Class` => `category/package/subpackage/class.php` – Hannes Oct 19 '10 at 09:39
  • @Hannes - yes, it did confuse me when I first saw it, but fortunately there was a logical pattern like you show, so once that was explained, it was fine. – Nathan Long Oct 19 '10 at 10:03
  • @Nathan Long thats for example the way Zend_Framework does it, works great! – Hannes Oct 19 '10 at 10:14
  • I believe it is only necessary in stateless applications like web applications, which is why you only see this functionality premade for you in web-centric languages. – dqhendricks Jan 10 '11 at 00:28
  • @Rolf "Glove that encases the thumb separately and the other four fingers together." – Nathan Long May 01 '11 at 23:45

5 Answers5

5

Both Ruby and PHP get it from AUTOLOAD in Perl.

Note that the AutoLoader module is a set of helpers for common tasks using the AUTOLOAD functionality.

Andy Lester
  • 91,102
  • 13
  • 100
  • 152
  • :-/ Perl's AUTOLOAD does something different. It allows you to dynamically interpret **method calls**. Missing classes won't be handled by Perl's AUTOLOAD. PHP's __autoload, in comparison, loads classes, but won't handle missing methods. – Sean McMillan Jul 02 '12 at 18:36
3
  1. Do not use __autoload(). It's a global thing so, by definition, it's somewhat evil. Instead, use spl_autoload_register() to register yet another autoloader to your system. This allows you to use several autoloaders, what is pretty common practice.
  2. Respect existing conventions. Every part of namespaced class name is a directory, so new MyProject\IO\FileReader(); should be in MyProject/IO/FileReader.php file.
  3. Magic is evil!

    The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"

    Rather such tricky code, use simple and verbose one:

    try {
        $mitten = new ToastMitten();
        // or $mitten = Mitten::factory('toast');
    } catch (ClassNotFoundException $cnfe) {
        $mitten = new BaseMitten();
    }
    
Crozin
  • 43,890
  • 13
  • 88
  • 135
  • Good points, but I don't necessarily agree with your example in #3. I can't give specific examples, but I'm familiar with a business case where the standard mitten, so to speak, is fine for many departments, at least initially, but any or all of them could eventually want a custom mitten. Say we need to loop through all departments and deploy the appropriate mitten. It's nice to be able to create a new Accounting_Mitten class, if necessary, and have it be automatically used for them, instead of having multiple try/catches or case statements in the factory that need updating. – Nathan Long Oct 19 '10 at 16:07
1

I think this feature comes in very handy, and I have not seen any features like it else where. Nor have I needed these features else where.

Petah
  • 45,477
  • 28
  • 157
  • 213
1

Java has something similar. It's called a ClassLoader. Probably other languages too, but they stick with some default implementation.

And, while we're at this. It would have been nice if __autoload loaded any type of symbols, not just classes: constants, functions and classes.

Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
1

See Ruby's Module#const_missing

I just learned this: Ruby has a method on Module called const_missing that gets called if you call Foo::Bar and Bar isn't in memory yet (although I suppose that Foo has to be in memory).

This example in ruby-doc.org shows a way to use that to implement an autoloader for that module. This is in fact what Rails uses to load new ActiveRecord model classes, according to "Eloquent Ruby" by Russ Olsen (Chapter 21, "Use method_missing for flexible error handling", which also covers const_missing).

It's able to do this because of the "convention over configuration" mindset: if you reference a model called ToastMitten, if it exists, it will be in app/models/toast_mitten.rb. If you could put that model any place you wanted, Rails wouldn't know where to look for it. Even if you're not using Rails, this example, and point #1 in my question, shows how useful it can be to follow conventions, even if you create them yourself.

Community
  • 1
  • 1
Nathan Long
  • 122,748
  • 97
  • 336
  • 451
  • Updated link to example: http://ruby-doc.org/core/Module.html#method-i-const_missing – gaRex Apr 08 '12 at 12:58
  • Why does it called bad, if it's just single possible method of implementing *true magic* autoloading without requires and autoloads? – gaRex Apr 08 '12 at 13:00
  • @gaRex - updated the link as you suggested. The negative description there has been removed, so I've removed it in my answer as well. – Nathan Long Apr 08 '12 at 18:21