Here's my attempt at this autoload for you.
I've slightly modified Emil Condrea's Answer.
To start, I'll show you the file structure of my classes:

As you can see above, the classes are set into seperate files and such to show.
Now taking Emil's answer and slightly changing it:
(Provided the file name is something like "Class.php" as seen above in the file structure)
function getClasses($path) {
$files = array();
$dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
foreach ($dir_iterator as $item) {
$pathname = $item->getPathName();
$filename = $item->getFileName();
if ($item->isDir()) {
getClasses($item);
} else {
$files[$filename] = $pathname;
}
}
return $files;
}
Will warrant a return array of files like the following [FILE_NAME] => [PATH_NAME]
:
Array
(
[Error.php] => /home2/DERP/public_html/something.com/watch/model/Site/Error.php
[Form.php] => /home2/DERP/public_html/something.com/watch/model/Site/Form.php
[Site.php] => /home2/DERP/public_html/something.com/watch/model/Site/Site.php
[Db.php] => /home2/DERP/public_html/something.com/watch/model/Database/Db.php
[Db_pdo.php] => /home2/DERP/public_html/something.com/watch/model/Database/Db_pdo.php
[Session.php] => /home2/DERP/public_html/something.com/watch/model/Security/Session.php
[Auth.php] => /home2/DERP/public_html/something.com/watch/model/Security/Auth.php
[Input.php] => /home2/DERP/public_html/something.com/watch/model/Security/Input.php
[Postcode.php] => /home2/DERP/public_html/something.com/watch/model/Postcode.php
[Rep.php] => /home2/DERP/public_html/something.com/watch/model/User/Rep.php
[User.php] => /home2/DERP/public_html/something.com/watch/model/User/User.php
[Notifications.php] => /home2/DERP/public_html/something.com/watch/model/User/Notifications.php
[Log.php] => /home2/DERP/public_html/something.com/watch/model/Log/Log.php
[Hook.php] => /home2/DERP/public_html/something.com/watch/model/Hook.php
)
Now that would've been called by something like the following:
getClasses(realpath(dirname(__FILE__)) . '/model')
Allowing us to run an __autoload()
like the following:
$model_classes = getClasses(realpath(dirname(__FILE__)) . '/model');
function __autoload($class_name) {
global $model_classes;
$filename = ucfirst($class_name) . '.php';
$model = $filename;
if (!isset($model_classes[$model])) {
// dead
return false;
} else {
// include first file (model)
include($model_classes[$model]);
}
}
Now
Obviously you shouldn't use global
but to me it seemed a far better alternative to running the getClasses()
function every single time within the __autoload()
function.
If someone else has anything to add, feel free! I just tried my own little method on this and it works without fault!
Note:
I was using
file_exists()
before and the above method is, in my opinion; a lot faster.
UPDATE
I had a brain wave just the other night and thought;
"Why not scan the application root and fetch all the php files then run a function to check if said file actually contains a class to make this as universal as possible.."
So I did a little research and found this nifty little function from php: token_get_all()
Now after a little digging through SO I found this answer: Determine class in file...
and after some modification, the getClasses()
function now looks like this:
function getClasses($path) {
$files = array();
$dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
foreach ($dir_iterator as $item) {
$pathname = $item->getPathName();
$filename = $item->getFileName();
if ($item->isDir()) {
get_classes($item);
} else {
if (substr($filename, -4) === '.php') {
if (get_php_classes(file_get_contents($pathname))) {
$files[$filename] = $pathname;
}
}
}
}
return $files;
}
With the addition of this new function from the above question:
function get_php_classes($php_code) {
$tokens = token_get_all($php_code);
$class_token = false;
foreach ($tokens as $token) {
if (is_array($token)) {
if ($token[0] == T_CLASS) {
$class_token = true;
} else if ($class_token && $token[0] == T_STRING) {
$classes[] = $token[1];
// $class_token = false;
}
}
}
return $class_token;
}
Now that allows you to simply run a $classes = getClasses(ROOTPATH)
and itterate through them.
DOWNFALL: each of the classes will have to have unique class names and/or file names. Unless somebody could lend their hand at a modification to allow.