Problems with Autoloader which autodetects classes - php

I'm currently programming on my Framework in PHP (mainly for education reasons, and a way of passing time). And I wrote an Autoloader which automatically scans the directory tree and detects all the classes in it and creates an array in the following format:
Array(
'MyAwesomeClass' => 'path/to/file/in/some/subdirectory/MyAwesomeClass.php',
'MyOtherAwesomeClass' => 'path/to/file/MyOtherAwesomeClass.php'
// ....
);
At first this was very neat. Because i don't needed to worry where I put my classes.
But later I discovered this is very resource intense. So I created an cache mechanism and the index is serialized and saved to a file. This decreased the response time of the PHP-Script by at least 50%. But it brought some issues with it.
In other classes in the framework I often use things like:
class_exists('MyAwesomeClassController');
The problem is if I added the new class MyAwesomeClassController the class is not yet in the index and class_exists returns false. The problem now is I have to delete the cached file (to let the autoloader recreate the index again) every time I add a new class to the Framework.
Another thing I tried (which is a bit hacky):
In the Autoloader class I checked if the auto load method was called using class_exists(). If this was the case I recreated the Index to see if I can find the requested class somewhere. But this doesn't seem to work out as well because sometimes class_exists is called using a class which mostly doesn't exists, so this is basicly the same solution as recreating the index on every request.
Any solutions? Or do I have to rewrite my Autoloader completely?

I went this path a time ago, and came to the same conclusion: to resource intensive. What you are actually doing here is building some kind of linker.
I switched to a combination of namespaces and a map. I map a namespace to a folder and when the autoloader is called, it strips of the namespace, looks up the corresponding folder, and includes the file.
my map looks like this (I choose xml for the format) :
<?xml version="1.0" encoding="UTF-8"?>
<autoloader>
<namespace id="Ganymedes\Core">/system/core</namespace>
<namespace id="Ganymedes\Core\Debug">/system/core/debug</namespace>
</autoloader>
And the class loader:
public function ClassLoader( $class )
{
if( class_exists( $class, false ))
return true;
$classparts = explode( '\\', $class );
$classfile = '/' . strtolower( array_pop( $classparts )) . '.php';
$namespace = implode( '\\', $classparts );
if( isset( $this->namespaces[$namespace] )) {
foreach ( $this->namespaces[$namespace] as $path )
if( is_readable( $path . $classfile ))
include_once $path . $classfile;
return true;
}
return false;
}

Maybe I haven't understood properly what you are trying to do... but what is wrong with get_include_path/set_include_path and the __autoload($class) built in function?
EDIT to explain my comment:
In "header.php" (file which gets included at the start of every script):
set_include_path(get_include_path().PATH_SEPARATOR."my/first/directory"
.PATH_SEPARATOR."my/second/directory"
.PATH_SEPARATOR."this/is/another/directory"
...
.PATH_SEPARATOR."and/here/is/the/last/one");
function __autoload($class) {
require_once($class.".class.php");
}
The autoload function checks each directory in the path, until it finds the required file. I've never checked it for performace, but I'm guessing that it is fairly insignificant unless you have 100s of directories. If you are organised, you can put your frequently used (base) classes in the first "extra" path so that they are found immediately.
I've just noticed in the PHP manual online that __autoload is no longer advised, and that spl_autoload_register should be used instead, but the concept is the same.

Under the assumption that the classes you're trying to load should always exist, your autoloader could do the following:
Look up the class name inside the map (which is cached). If it exists, load the file.
If it doesn't exist, perform another scan and look up the class name in the newly generated map. If it exists, write the new map to disc and load the file.
If it still doesn't exist, raise the alarm.
The third step could be improved by introducing a negative cache as well; if the class is present in that map, you know the class doesn't exist based on a previous attempt. The negative cache would be shorter lived but just long enough to not trash your server.
You could also consider creating the cache offline as part of a deployment system.

Related

PHP & Composer: Runtime check if class is autoloadable

Recently I decided to upgrade some projects from my own (...) autoloader solution to a Composer PSR-4 autoloader. My code already followed PSR-4 so, no big deal there.
On a specific case, I had the following code:
public static function isAutoLoadable($className)
{
$className = ltrim($className, "\\");
$file = $GLOBALS["Path"] . "/src/" . str_replace("\\", "/", $className) . ".php";
if (false !== stream_resolve_include_path($file))
return $file;
return false;
}
It allowed me to check whatever a given class name could be loaded, without actually trying to load it and result on a PHP Class * not found error.
Use case:
I'm currently using it to replace controllers that by some reason couldn't be found with a generic error one, avoiding an App crash and just telling the user something went wrong... then extra internal logging is done.
A function would be good since I can call it before trying to load a controller... I don't want this behavior to spread to any other classes on the app
So my question is: Is there a equivalent way to check if Composer is able to autoload some class without forcing it to load it and cause an error? -- So I can take further actions in case the class wasn't found?

Autoloaders in PHP - two running at a time

I understand how to register autoloaders and even how to create one, that's no issue at all. How ever the main issue is - how do you have two auto loaders running side by side for something like:
class project_one_folder_class extends project_two_folder_class{}
You'll notice that the child class belongs to a project which is reaching out and calling the parent class which is locate in a different project.
The way the projects are linked project two's classes are always seen by the auto loader, how ever project one's classes are never seen.
So the way I thought around this was to write two auto loaders and register them because php will look in on then the other. How ever php seems to be looking in only one and not the other.
how would you solve this?
Edit
Project two is parent, Project one is child. This is more expanded question then What was posted on this question.
To better expand this is my class.
class AisisCore_Loader_AutoLoader{
protected static $_instance;
public function get_instance(){
if(null == self::$_instance){
self::$_instance = new self();
}
return self::$_instance;
}
public function reset_instance(){
self::$_instance = null;
}
public function register_auto_loader(){
spl_autoload_register(array($this, 'load_class'));
spl_autoload_register(array($this, 'load_child_class'));
}
public function load_class($class){
$path = str_replace('_', '/', $class);
if(file_exists(get_template_directory() . '/' . $path . '.php')){
require_once(get_template_directory() . '/' . $path . '.php');
}
}
public function load_child_class($class){
$path = str_replace('_', '/', $class);
if(file_exists(get_stylesheet_directory() . '/' . $path . '.php')){
require_once(get_stylesheet_directory() . '/' . $path . '.php');
}
}
}
Currently this class will load anything in the parent project. It will even load parent project objects in the child project. How ever no child object can be loaded using this class as it is not found.
Those familiar with WordPress will instantly say, yes its because you have get_template_directory when you want get_stylesheet_directory How ever - Knowing this - I want to write then two auto loaders, one that will load child projects objects using get_stylesheet_directory and then one that will load parent objects via get_stylesheet_directory so that:
class project_one_folder_class extends project_two_folder_class{}
works and loads, with out error.
This is a little rough, but you actually only need one autoloader that just checks within multiple directories:
abstract class Hakre_Theme_AutoLoader
{
public static $directories;
public static function init()
{
// configure paths
self::$directories = array(
get_template_directory(), // current theme, parent in case of childtheme
get_stylesheet_directory(), // current theme, child in case of childtheme
);
// please double check if you really need to prepend
return spl_autoload_register('Hakre_Theme_AutoLoader::autoload', true, true);
}
public static function autoload($class)
{
$filename = str_replace('_', '/', $class) . '.php';
foreach (self::$directories as $directory) {
$path = $directory . '/' . $filename;
if (is_file($path)) {
require($path);
return; # leave because the class has been loaded
}
}
}
}
Hakre_Theme_AutoLoader::init();
## If you're unsure all worked out properly:
var_dump(Hakre_Theme_AutoLoader::$directories);
This should actually do it, however I've not tested it. See the var_dump, you can debug if the correct directories are registered or not. No need to have multiple callbacks only because you want to check in two directories.
Well, of course you could just look up a second path when the first file_exists returns false - in the very same autoloader.
You can also register a second autoloader for the second path.
PHP docs addresses this:
If there must be multiple autoload functions, spl_autoload_register() allows for this. It effectively creates a queue of autoload functions, and runs through each of them in the order they are defined. By contrast, __autoload() may only be defined once.
Separate the autoloading process!
PHP is working like this: At some point, the code execution stumbles upon a class reference that is not yet loaded. $obj = new project_one_folder_class()
Now the registered autoloader functions are called, starting with the one added first (unless the ones added later are using the "prepend" parameter).
The first (and all subsequent) autoload function gets the name of the class that should be loaded. The function now has the task to decide
Is it it's task to load this class? If not, do nothing, let the other functions try to load it.
If this function is responsible to load the class, try to make up a path and filename out of the known class name, and require this file.
Step 1 is usually solved by looking if the class name to be loaded starts with a certain prefix. In your case, the autoloader responsible for loading classes starting with "project_one_" should NOT try to load any other classes starting with something else.
Step 2 takes place if the autoloader knows that it must perform the autoloading. It now transforms the class name into a relative path and filename, adds the base directory, and then requires the file.
Requiring a file that defines a class which extends another class (or implements interfaces) can then trigger another run of autoloading with any still unknown classes. In your case, the autoload process is started again with the class name "project_two_folder_class". Note that the first autoloader for "project_one_" classes will be called again with this second class name, but it must not do anything, because it does not know how to load these classes. This is up to the autoloader that knows about "project_two_" classes.
Order of registration should not matter for the different autoloaders. If it does, autoloaders misbehave.
Because it is a common pattern to simply transform any underscore characters in class names into DIRECTORY_SEPARATOR, as well as the backslashes from namespaces, add ".php" at the end, and then try to load this file from a defined base directory, the code for two of these autoloaders will be identical, and the problem is reduced to configuring only one autoload function with these two cases: Which prefix should be present, and in which base directory should the file be expected to be, provided that the class name can be transformed into a relative path to the file.
Checking in every case whether the file exists in a certain directory or not is not optimal for performance. You'll end up doing plenty of checks for files that you will be able to know you cannot load by simply looking at the class name.
And by the way: Autoloader functions do not need to be singletons. In fact, your singleton implementation is broken, and useless. Instantiate the autoloader with new, maybe pass some configuration values into the constructor, and call spl_autoload_register(), and you should be done.
You can add more than one loader, just register each function with spl_autoload_register().
procedural style:
spl_autoload_register('loader_function1'));
// your second class location
spl_autoload_register('loader_function2'));
or in a OO style
spl_autoload_register(array($this, 'loader_function1'));
spl_autoload_register(array($this, 'loader_function2'));
However based on your question: you probably can accomplish the same thing by having a more flexible autoloader
see my answer in a different question here:
Class autoloader in wordpress plugin

Efficient PHP auto-loading and naming strategies

Like most web developers these days, I'm thoroughly enjoying the benefits of solid MVC architecture for web apps and sites. When doing MVC with PHP, autoloading obviously comes in extremely handy.
I've become a fan of spl_autoload_register over simply defining a single __autoload() function, as this is obviously more flexible if you are incorporating different base modules that each use their own autoloading. However, I've never felt great about the loading functions that I write. They involve a lot of string checking and directory scanning in order to look for possible classes to load.
For example, let's say I have an app that has a base path defined as PATH_APP, and a simple structure with directories named models, views and controllers. I often employ a naming structure whereby files are named IndexView.php and IndexController.php inside the appropriate directory, and models generally have no particular scheme by default. I might have a loader function for this structure like this that gets registered with spl_autoload_register:
public function MVCLoader($class)
{
if (file_exists(PATH_APP.'/models/'.$class.'.php')) {
require_once(PATH_APP.'/models/'.$class.'.php');
return true;
}
else if (strpos($class,'View') !== false) {
if (file_exists(PATH_APP.'/views/'.$class.'.php')) {
require_once(PATH_APP.'/views/'.$class.'.php');
return true;
}
}
else if (strpos($class,'Controller') !== false) {
if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) {
require_once(PATH_APP.'/controllers/'.$class.'.php');
return true;
}
}
return false;
}
If it's not found after that, I might have another function to scan sub-directories in the models directory. However, all the if/else-ing, string checking and directory scanning seems inefficient to me, and I'd like to improve it.
I'm very curious what file naming and autoloading strategies other developers might employ. I'm looking specifically for good techniques to employ for efficient autoloading, and not alternatives to autoloading.
This is what I have been using in all of my projects (lifted straight from the source of the last one):
public static function loadClass($class)
{
$files = array(
$class . '.php',
str_replace('_', '/', $class) . '.php',
);
foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path)
{
foreach ($files as $file)
{
$path = "$base_path/$file";
if (file_exists($path) && is_readable($path))
{
include_once $path;
return;
}
}
}
}
If I look for SomeClass_SeperatedWith_Underscores it will look for SomeClass_SeperatedWith_Underscores.php followed by SomeClass/SeperatedWith/Underscores.php rooted at each directory in the current include path.
EDIT: I just wanted to put out there that I use this for efficiency in development, and not necessarily processing time. If you have PEAR on your path then with this you can just use the classes and don't have to include them when you need them.
I tend to keep my classes in a hierarchy of directories, with underscores breaking up namespaces... This code lets me keep the file structure nice and tidy if I want, or to inject a quick class file without nested directories if I want (for adding a single class or two to a library that it is defendant on, but not part of the project I am currently working on.)
I landed on this solution:
I created a single script that traverses my class library folder (which contains subfolders for separate modules / systems), and parses the file contents looking for class definitions. If it finds a class definition in a php file (pretty simple regex pattern), it creates a symlink:
class_name.php -> actual/source/file.php
This lets me use a single, simple autoload function that needs only the class name and the path to the main symlink folder, and doesn't have to do any path/string manipulation.
The best part is that I can rearrange my source code completely or add a new subsystem and just run the link generating script to have everything autoloaded.
If you want efficiency then you shouldn't be using the autoload feature at all. The autoload feature is for being lazy. You should be providing an explicit path to your include files when you include them. If your autoload function can find these files then you could code to find them explicitly. When you are working on the view part of the code and about to load a new view class, by letting the autoload function handle it, it first assumes your class is a model class? That's inefficient. Instead your code should just be:
include_once $this->views_path . $class . '.php';
If you need multiple "view" paths, make a function that loads views:
public function load_view($class) {
// perhaps there's a mapping here instead....
foreach ($this->views_paths as $path) {
$filename = $path . $class . '.php';
if (file_exists($filename)) {
include_once $filename;
}
}
throw ....
}
In any case, at the point where the include occurs, you have the greatest/most accurate information about the class you want to load. Using that information to load the class fully is the only efficient class loading strategy. Yes, you may end up with more class variables or (heaven forbid) some global variables. But that is a better tradeoff than just being lazy and scanning parts of the file system for your class.

Would performance suffer using autoload in php and searching for the class file?

I've always struggled with how to best include classes into my php code. Pathing is usually an issue but a few minutes ago i found this question which dramatically helps that. Now I'm reading about __autoload and thinking that it could make the process of developing my applications much easier. The problem is i like to maintain folder structure to separate areas of functionality as opposed to throwing everything into a general /lib folder. So if i override autoload to do a deep search of a class folder including all subfolders, what performance hits can i expect?
Obviously this will depend on scale, depth of the folder structure and number of classes but generally I'm asking on a medium scale project will it cause problems.
__autoload is great, but the cost of stating all the files in a recursive search function is expensive. You might want to look at building a tree of files to use for autoloading. In my framework, I consistently name files for their classes and use a map that is cached for the data.
Check out http://trac.framewerk.org/cgi-bin/trac.fcgi/browser/trunk/index.php [dead link] starting at line 68 for an idea of how this can be done.
Edit: And to more directly answer your question, without caching, you can expect a performance hit on a site with medium to heavy traffic.
A common pattern (Pear, Zend Framework as examples...) is to make the classname reflect the path, so Db_Adapter_Mysql will be in at /Db/Adapter/Mysql.php, from somewhere that's added to the include-path.
There are 2 ways that you could easily do this, first of all, name your classes so that they'll define the structure of where to find them
function __autoload($classname)
{
try
{
if (class_exists($classname, false) OR interface_exists($classname, false))
{
return;
}
$class = split('_', strtolower(strval($classname)));
if (array_shift($class) != 'majyk')
{
throw new Exception('Autoloader tried to load a class that does not belong to us ( ' . $classname . ' )');
}
switch (count($class))
{
case 1: // Core Class - matches Majyk_Foo - include /core/class_foo.php
$file = MAJYK_DIR . 'core/class_' . $class[0] . '.php';
break;
case 2: // Subclass - matches Majyk_Foo_Bar - includes /foo/class_bar.php
$file = MAJYK_DIR . $class[0] . '/class_' . $class[1] . '.php';
break;
default:
throw new Exception('Unknown Class Name ( ' . $classname .' )');
return false;
}
if (file_exists($file))
{
require_once($file);
if (!class_exists($classname, false) AND !interface_exists($classname, false))
{
throw new Exception('Class cannot be found ( ' . $classname . ' )');
}
}
else
{
throw new Exception('Class File Cannot be found ( ' . str_replace(MAJYK_DIR, '', $file) . ' )');
}
}
catch (Exception $e)
{
// spl_autoload($classname);
echo $e->getMessage();
}
}
Or, 2, use multiple autoloaders. PHP >=5.1.2 Has the SPL library, which allows you to add multiple autoloaders. You add one for each path, and it'll find it on it's way through. Or just add them to the include path and use the default spl_autoload()
An example
function autoload_foo($classname)
{
require_once('foo/' . $classname . '.php');
}
function autoload_bar($classname)
{
require_once('bar/' . $classname . '.php');
}
spl_autoload_register('autoload_foo');
spl_autoload_register('autoload_bar');
spl_autoload_register('spl_autoload'); // Default SPL Autoloader
Autoload is great PHP feature that helps you very much...
The perfomance wouldn't suffer if will use the smart taxonomy like:
1. every library stays in the folders "packages"
2. every class is located by replacing the "_" in the class name with the "/" and adding a ".php" at the end
class = My_App_Smart_Object
file = packages/My/App/Smart/Object.php
The benefits of this approach(used by almost any framework) is also a smarter organization of your code :-)
Hunting for files all over the place will make things slower (many more disk hits). Loading all of your classes in case you might need them will make things take more memory. Specifying which classes you need in every file is difficult to maintain (i.e. they don't get removed if they're no longer used).
The real question is which of these is more important to you? They're all tradeoffs, in the end, so you have to pick one. It's arguable, though, that most of the overhead in the second and third options has to do with actually compiling the code. Using something like APC can significantly reduce the overhead of loading and compiling every class on every page load.
Given the use of APC, I would likely take the approach of dividing up my code into modules (e.g. the web interface module, the database interaction module, etc.) and have each of those modules import all the classes for their module, plus classes from other modules they may need. It's a tradeoff between the last two, and I've found it works well enough for my needs.
I tend to use a simple approach where __autoload() consults a hash mapping class names to relative paths, which is contained in a file that's regenerated using a simple script which itself performs the recursive search.
This requires that the script be run when adding a new class file or restructuring the code base, but it also avoids "cleverness" in __autoload() which can lead to unnecessary stat() calls, and it has the advantage that I can easily move files around within my code base, knowing that all I need to do is run a single script to update the autoloader.
The script itself recursively inspects my includes/ directory, and assumes that any PHP file not named in a short list of exclusions (the autoloader itself, plus some other standard files I tend to have) contains a class of the same name.
Zend Framework's approach is to do autoload based on the PEAR folder standard (Class_Foo maps to /Class/Foo.php), however rather than using a set base path it uses the include_path.
The problem with their approach is there's no way to check beforehand if a file exists so the autoload will try to include a file that doesn't exist in any of the include_path's, error out, and never give any other autoload functions registered with spl_autoload_register a chance to include the file.
So a slight deviation is to manually provide an array of base paths where the autoload can expect to find classes setup in the PEAR fashion and just loop over the base paths:
<?php
//...
foreach( $paths as $path )
{
if( file_exists($path . $classNameToFilePath) )
include $path . $classNameToFilePath;
}
//...
?>
Granted you'll kinda be search but for each autoload you'll only be doing at worst n searches, where n is the number of base paths you are checking.
But if you find yourself still having to recursively scan directories the question is not "Will autoload hurt my performance," the question should be "why am I tossing my class files around in a random structure?" Sticking to the PEAR structure will save you so many headaches, and even if you decide to go with manually doing your includes as opposed to autoload, there will be no guessing as to where the class files are located when you do your include statements.

How to handle including needed classes in PHP

I'm wondering what the best practice is for handling the problem with having to "include" so many files in my PHP scripts in order to ensure that all the classes I need to use are accessible to my script.
Currently, I'm just using include_once to include the classes I access directly. Each of those would include_once the classes that they access.
I've looked into using the __autoload function, but hat doesn't seem to work well if you plan to have your class files organized in a directory tree. If you did this, it seems like you'd end up walking the directory tree until you found the class you were looking for. Also, I'm not sure how this effects classes with the same name in different namespaces.
Is there an easier way to handle this?
Or is PHP just not suited to "enterprisey" type applications with lots of different objects all located in separate files that can be in many different directories.
I my applications I usually have setup.php file that includes all core classes (i.e. framework and accompanying libraries). My custom classes are loaded using autoloader aided by directory layout map.
Each time new class is added I run command line builder script that scans whole directory tree in search for model classes then builds associative array with class names as keys and paths as values. Then, __autoload function looks up class name in that array and gets include path. Here's the code:
autobuild.php
define('MAP', 'var/cache/autoload.map');
error_reporting(E_ALL);
require 'setup.php';
print(buildAutoloaderMap() . " classes mapped\n");
function buildAutoloaderMap() {
$dirs = array('lib', 'view', 'model');
$cache = array();
$n = 0;
foreach ($dirs as $dir) {
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $entry) {
$fn = $entry->getFilename();
if (!preg_match('/\.class\.php$/', $fn))
continue;
$c = str_replace('.class.php', '', $fn);
if (!class_exists($c)) {
$cache[$c] = ($pn = $entry->getPathname());
++$n;
}
}
}
ksort($cache);
file_put_contents(MAP, serialize($cache));
return $n;
}
autoload.php
define('MAP', 'var/cache/autoload.map');
function __autoload($className) {
static $map;
$map or ($map = unserialize(file_get_contents(MAP)));
$fn = array_key_exists($className, $map) ? $map[$className] : null;
if ($fn and file_exists($fn)) {
include $fn;
unset($map[$className]);
}
}
Note that file naming convention must be [class_name].class.php. Alter the directories classes will be looked in autobuild.php. You can also run autobuilder from autoload function when class not found, but that may get your program into infinite loop.
Serialized arrays are darn fast.
#JasonMichael: PHP 4 is dead. Get over it.
You can define multiple autoloading functions with spl_autoload_register:
spl_autoload_register('load_controllers');
spl_autoload_register('load_models');
function load_models($class){
if( !file_exists("models/$class.php") )
return false;
include "models/$class.php";
return true;
}
function load_controllers($class){
if( !file_exists("controllers/$class.php") )
return false;
include "controllers/$class.php";
return true;
}
You can also programmatically determine the location of the class file by using structured naming conventions that map to physical directories. This is how Zend do it in Zend Framework. So when you call Zend_Loader::loadClass("Zend_Db_Table"); it explodes the classname into an array of directories by splitting on the underscores, and then the Zend_Loader class goes to load the required file.
Like all the Zend modules, I would expect you can use just the loader on its own with your own classes but I have only used it as part of a site using Zend's MVC.
But there have been concerns about performance under load when you use any sort of dynamic class loading, for example see this blog post comparing Zend_Loader with hard loading of class files.
As well as the performance penalty of having to search the PHP include path, it defeats opcode caching. From a comment on that post:
When using ANY Dynamic class loader APC can’t cache those files fully as its not sure which files will load on any single request. By hard loading the files APC can cache them in full.
__autoload works well if you have a consistent naming convention for your classes that tell the function where they're found inside the directory tree. MVC lends itself particularly well for this kind of thing because you can easily split the classes into models, views and controllers.
Alternatively, keep an associative array of names to file locations for your class and let __autoload query this array.
Of the suggestions so far, I'm partial to Kevin's, but it doesn't need to be absolute. I see a couple different options to use with __autoload.
Put all class files into a single directory. Name the file after the class, ie, classes/User.php or classes/User.class.php.
Kevin's idea of putting models into one directory, controllers into another, etc. Works well if all of your classes fit nicely into the MVC framework, but sometimes, things get messy.
Include the directory in the classname. For example, a class called Model_User would actually be located at classes/Model/User.php. Your __autoload function would know to translate an underscore into a directory separator to find the file.
Just parse the whole directory structure once. Either in the __autoload function, or even just in the same PHP file where it's defined, loop over the contents of the classes directory and cache what files are where. So, if you try to load the User class, it doesn't matter if it's in classes/User.php or classes/Models/User.php or classes/Utility/User.php. Once it finds User.php somewhere in the classes directory, it will know what file to include when the User class needs to be autoloaded.
#Kevin:
I was just trying to point out that spl_autoload_register is a better alternative to __autoload since you can define multiple loaders, and they won't conflict with each other. Handy if you have to include libraries that define an __autoload function as well.
Are you sure? The documentation says differently:
If your code has an existing __autoload function then this function must be explicitly registered on the __autoload stack. This is because spl_autoload_register() will effectively replace the engine cache for the __autoload function by either spl_autoload() or spl_autoload_call().
=> you have to explicitly register any library's __autoload as well. But apart from that you're of course right, this function is the better alternative.
__autoload will work, but only in PHP 5.

Categories