views:

199

answers:

5

I have a problem with my autoloader:

public function loadClass($className) {
    $file = str_replace(array('_', '\\'), '/', $className) . '.php';
    include_once $file;
}

As you can see, it's quite simple. I just deduce the filename of the class and try to include it. I have a problem though; I get an exception when trying to load a non-existing class (because I have an error handler which throws exceptions). This is inconvenient, because it's also fired when you use class_exists() on a non-existing class. You don't want an exception there, just a "false" returned.

I fixed this earlier by putting an @ before the include (supressing all errors). The big drawback with this, though, is that any parser/compiler errors (that are fatal) in this include won't show up (not even in the logs), resulting in a hard to find bug.

What would be the best way to solve both problems at once? The easiest way would be to include something like this in the autoloader (pseudocode):

foreach (path in the include_path) {
    if (is_readable(the path + the class name)) readable = true;
}
if (!readable) return;

But I worry about the performance there. Would it hurt a lot?


(Solved) Made it like this:

public function loadClass($className) {

 $file = str_replace(array('_', '\\'), '/', $className) . '.php'; 
 $paths = explode(PATH_SEPARATOR, get_include_path());
 foreach ($paths as $path) {
  if (is_readable($path . '/' . $file)) {
                        include_once $file;
                        return;
                    }
 }

}
A: 

It will only get called once per class, so performance shouldn't be a problem.

JW
A: 
 public function loadClass($className) {
     $file = str_replace(array('_', '\\'), '/', $className) . '.php';
     if(is_readable($file))
       include_once $file;
 }

is_readable won't make a huge performance difference.

scragar
Except that I'll have to do it for every include path (which there are about 4 on average, i'd guess).
Bart van Heukelom
A: 

class_exists() has a second parameter autoload which, when set to FALSE, won't trigger the autoloader for a nonexistant class.

MathieuK
I know and if I set that to false the whole function is pretty useless to me. ;)
Bart van Heukelom
A: 

(Solved) Made it like this:

public function loadClass($className) {

 $file = str_replace(array('_', '\\'), '/', $className) . '.php'; 
 $paths = explode(PATH_SEPARATOR, get_include_path());
 foreach ($paths as $path) {
  if (is_readable($path . '/' . $file)) {
                        include_once $file;
                        return;
                    }
 }

}
Bart van Heukelom
A: 

Use the PHP Autoloader. It finds your classes automatically, knows namespaces and uses an index.

PHP Autoloader