Autoloading

Tim Bureck

Erfahrenes Mitglied
Hallo zusammen,

folgendes Problem: Ich habe eine Klasse, die ein Interface implementiert. Allerdings bekomme ich sobald ich eine Instanz dieser Klasse erstellen möchte den folgenden Fehler:

Fatal error: Interface 'Command' not found

Soweit kein Problem, die Definitionen stehen ja auch nicht in derselben Datei und es gibt keine Includes. Allerdings habe ich eine Autoload-Funktion geschrieben, die auch funktioniert:

PHP:
function __autoload($className) {
    searchClass(CSMTOOLS_DIR.'/library', $className);
}

function searchClass($dir, $className) {
    if(!is_dir($dir)) {
        return false;
    }

    $dirInputHandler = opendir($dir);
    $dirContent = scandir($dir);

    while(($dirElement = readdir($dirInputHandler)) !== false) {
        if($dirElement != "." && $dirElement != ".."
                && $dirElement != ".svn"
                && is_dir($dir."/".$dirElement)) {
            if (searchClass($dir."/".$dirElement, $className)) {
                return true;
            }
        } elseif($dirElement != "." && $dirElement != "..") {
            if(preg_match("/".$className.".class.php/",
                    $dir."/".$dirElement) > 0) {
                require_once $dir."/".$dirElement;
                return true;
            }
        }
    }

    closedir($dirInputHandler);
    return false;
}

Woher weiß ich das? Vorher wurden auch schon Klassen mittels Autoloader geladen. Sobald ich aber an diese Stelle komme:

PHP:
abstract class BlockCommand implements Command {
    ...
}

tritt der Fehler auf. Die Frage nun:

Warum klappt das Autoloading hier nicht?

PS: Die Datei Command.class.php existiert natürlich inklusive des Interfaces Command :)
 
Wenn bis heute Abend niemand eine Idee hat, stelle ich mal mehr Source zu Verfügung.

Hat vielleicht noch jemand eine Idee wo man sich da schlau machen könnte?
 
Schreibe deine "Funktion" einfach mal in __autoload direkt rein.
Könnte sein das der Gültigkeitsbereich für das require sich auf die Funktion beschränkt.

EDIT: Hier noch was zum lesen. Autoload hat Probleme bei extends etc: http://bugs.php.net/bug.php?id=44848
 
Zuletzt bearbeitet:
Das Problem hatte ich auch letztens und bekam es auch nicht durch die autoload Methode gelöst...

Das Problem scheint irgendein Verzeichniskonflikt zu sein.
Denn selbst wenn bei mir das Interface auf der gleichen Ebene lag wie die Klasse hat meine autoload Funktion nicht das geladen was ich wollte...

Ich inkludiere die Dateien jetzt in der Klasse und lade sie nicht dynamisch nach.
 
Zum Haare raufen.. der Bugreport hat mich nochmal dazu bewegt den Debugger anzuwerfen, der Fehler ist gefunden. Und zwar hat die searchClass($dir, $className) einen kleinen Schönheitsfehler:

PHP:
if(preg_match("/".$className.".class.php/",
    $dir."/".$dirElement) > 0) {

Eigentlich wird zuerst die Klasse InlineCommand, die ebenfalls das Interface Command implementiert, geladen. Nun stößt PHP bereits auf dieses Interface und lädt es. Der reguläre Ausdruck prüft allerdings noch nicht genau genug und findet zuerst... genau, die BlockCommand.class.php.

Und genau an dieser Stelle ist dann der Fehler aufgetreten, da auf einmal wieder das Interface Command auftritt, aber er denkt wohl, dass er das gerade lädt.

Die Lösung des Problems ist dann recht simpel:

PHP:
if(preg_match("@/".$className.".class.php$@",
    $dir."/".$dirElement) > 0) {

Ich überprüfe nun wirklich ob es genau die Datei ist, indem ich ein / voranstelle. Mit dem Dollar am Ende stelle ich noch sicher, dass nicht vielleicht ein Verzeichnis so heißt.

Das war aber auch mal ein blöder Fehler.. Vielen Dank jedenfalls für die Hinweise. :)
 
Okay, danke! Schade, dass der DirectoryIterator nicht soo gut dokumentiert ist, aber das werd ich wohl auch noch hinbekommen. ^^ Die Optimierungen kommen allerdings erst später, erstmal soll alles so weit funktionieren.. und damit ich es nicht vergesse wird ein TODO rein geschrieben. :)

*als erledigt markier*
 
Zuletzt bearbeitet:
Zurück