autoloader with upper and lowercase classname
Question
I am using this class in php for autoloading. http://pastebin.com/m75f95c3b
But when I have somewhere
class Bar extends Foo
And I have a file called foo.class.php it won't find the class. But when i chagne the filename to Foo.class.php it will find the class.
I am trying to add some functionallity to my class to always find the file if its there no matter wether the filename starts with a capital or not. But so far I haven't scuceeded.
Anyone?
Solution
Gumbo's solution is the best one and that's what almost everyone uses. I do not understand why you do not like. Of course you can first check whether a file with the class name capitalized exists or not, and if not then check whether lowercased version exists or not. That's definitely not better than Gumbo's solution. After all "your" programmers have to follow some conventions/rules.
OTHER TIPS
If all of your file have lowercase names, apply strtolower
to the $className
variable value in each method of your class:
$className = strtolower($className);
But I suggest that you draft some coding guidelines that every developer has to stick to. Otherwise you will have to test each of the 2<length of file name> possibilities of writing a file name using uppercase and lowercase letters.
I'd do it more or less like this
function __autoload($class_name) {
$upperName = strtoupper(substr($class_name,0,1)) . substr($class_name, 1);
$lowerName = strtolower(substr($class_name,0,1)) . substr($class_name, 1);
//Check to see if the class file exists as-is
if(file_exists($class_name . '.php')) {
require_once($class_name . '.php');
}elseif(file_exists($upperName . '.php')) {
require_once($upperName . '.php');
}elseif(file_exists($lowerName . '.php')) {
require_once($lowerName . '.php');
}else {
throw new Exception("The class $class_name could not be found.");
}
}
It's easy to enough to add other conditionals as different naming conventions arise.
I use an __autoload() function that takes into account several different file naming conventions to provide backwards compatibility with previous developers.
It does a simple loop over each convention and checks to see if that file exists. If the file exists, then it loads it.
For my function, I do this for different file extensions, such as .inc, .class or .inc.php . You could do the same, but search for upper and lower first characters.
I would put this in the searchForClassFile() method, in the else part with the comment 'Found a file'.
EDIT (more information):
Rather than recursively descend into a class directory looking for the correct file, I map the class name to a specific location. This is a common practice. For example, foo_bar
is mapped to [CLASS_DIRECTORY]/foo/bar.[EXTENSION]
. In our case, we check several different extensions.
In your case, you have to make a design decision about how you want to search for the class file, but modifying your code:
} else {
// Found a file
if ($f == $className . self::$classFileSuffix ||
$f == strtolower($className) . self::classFileSuffix) {
return $subPath;
}
}
Instead of strtolower() you could write a function that only lowers the first character, or if using PHP > 5.3.0 (not officially released) use the lcfirst() function.
You can use an autoloader that scans the directories for .php files, and actually looks into the contents of each file for patterns such as "class Foo" using a regular expression. You will need to cache this, of course, preferably by using an array of the form class => directory. You also need to make sure you invalidate the cache correctly, e.g. when there are new .php files in the folder.
I do this for my website, and it works great.