2013-07-23 12 views
5

Ich experimentierte mit Autoloader Klassenverzeichnis Mapping-Techniken, und es war ein bisschen ein Kampf. Es gelang mir, eine ziemlich einfache Lösung (oberflächlich) zu finden, aber ich bin völlig verwirrt, dass es überhaupt funktioniert, während andere, "offensichtlicher" Lösungen versagten. Im Folgenden finden Sie einige Codefragmente, die meine Verwirrung verdeutlichen.php autoloader: warum funktioniert das?

Hier ist der Arbeitscode:

<?php 
    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) { 
     $classMap = array(
      'classes/', 
      'classes/sites/', 
      'classes/data/' 
     ); 
     foreach ($classMap as $location) { 
      if ([email protected]_once($location . $class . '.php')) { // @ SUPPRESSES include_once WARNINGS 
       // CLASS DOESN'T EXIST IN THIS DIRECTORY 
       continue; 
      } else { 
       // CLASS IS AUTO-LOADED 
       break; 
      } 
     } 
    } 
?> 

Hier ist ein Ausschnitt, den ich sollte Arbeit gefühlt, aber nicht:

<?php 
    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) { 
     $classMap = array(
      'classes/', 
      'classes/sites/', 
      'classes/data/' 
     ); 
     foreach ($classMap as $location) { 
      if (file_exists($location . $class . '.php')) { 
       require_once ($location . $class . '.php'); 
      } 
     } 
    } 
?> 

Letzteres mehr Sinn für mich macht, denn während diese beiden Versionen funktionieren:

<?php 
    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) { 
     require_once ('classes/sites/' . $class . '.php'); 
    } 
?> 

<?php 
    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) {     
     $location = 'classes/sites/';     
     require_once ($location . $class . '.php'); 
    } 
?> 

Dieser wirft "Keine solche Datei oder Verzeichnis ..." (Beachten Sie das Fehlen von "Sites /" im Pfad.

<?php 
    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) { 
     require_once ('classes/' . $class . '.php'); 
    } 
?> 

Die „Keine solche Datei oder das Verzeichnis ...“ Fehler hat mich glaube ich einfach für eine Klasse unterstützt Datei überprüfen konnte, und wenn (file_exists()) {require_once(); break;} else {continue;}

Warum funktioniert das nicht? Und warum funktioniert das erste Snippet? Der unterstützende Pfad/die Datei ist niemals explizit enthalten oder erforderlich.

+0

ist das übergeordnete Verzeichnis der Klassen Pfad in Ihrem include_paths? – Orangepill

+0

Die unterstützende Datei ist enthalten, es wird nur in der if-Anweisung kombiniert: if (! @include_once ($ location. $ Class. '.php')) –

+0

Ja, ich dachte das, John500, aber hoffte auf Bestätigung Also vielen Dank dafür. Es fühlt sich an, als wäre ich ein sehr schlampiger Weg, um das zu erreichen, was ich brauche, aber das verdirbt nur meinen Juckreiz, um die Lösung zu verbessern. Orangepill, ich bin mir nicht sicher, wie ich das machen soll ... Ich habe seit einiger Zeit nicht mehr mit PHP gearbeitet, und als ich das letzte Mal getan habe, war ich nicht mehr so ​​gut programmiert wie jetzt ... also ich Ich hack 'im Grunde bei PHP und versuche Dinge zu tun, die ich bereits in Java und ColdFusion zu tun weiß;). –

Antwort

1

OK, ich habe es herausgefunden. Mein Problem war in der Tat nicht den Pfad richtig einzurichten; mit der __DIR__ Konstante war der :: ahem :: Weg zum Erfolg. Hier ist der Arbeits Code, den ich jetzt bin mit:

<?php 
    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) { 
     $classMap = array(
      'classes/', 
      'classes/sites/', 
      'classes/data/' 
     ); 
     foreach ($classMap as $location) { 
      if (file_exists(__DIR__ . '/' . $location . $class . '.php')) { 
       require_once(__DIR__ . '/' . $location . $class . '.php'); 
       break; 
      } 
     } 
    } 
?> 

Es stellt sich heraus __DIR__ gibt den Speicherort der aktuellen Datei, in der sie genannt wird (im Gegensatz zu, sagen wir, eine Datei, die es einschließlich), die Dies bedeutet, dass dies so lange funktioniert, wie diese Datei im Stammverzeichnis des Verzeichnisses mit dem Verzeichnis/classes verbleibt. Und es existiert ausschließlich für die Definition dieser Arten von Einstellungen ...

Hoffe, das hilft jemand anderen auf der ganzen Linie! Und natürlich, wenn jemand Licht auf warum diese Lösung ist suboptimal, bin ich alle Augen ...

EDIT: Eine Optimierung, die ich durchführen werde, wird die $ classMap Array() zu konvertieren (zB auf ein assoziatives Array ,. $classMap = array('root' => 'classes/', 'sites' => 'classes/sites/'); so kann ich eine Lookup tun, anstatt eine Schleife durch alle Verzeichnisse ich im Laufe der Zeit erstellen Aber ich nehme an, dass für einen anderen Thread ist

EDIT2:.. Wenn jemand interessiert ist, ist hier die Lösung, die ich mir als assoziatives Array ausgedacht habe: Im Grunde stelle ich ein assoziatives Array in $ GLOBALS auf und benutze das, um eine Map von Classes -> Packages zu speichern, dann ordne ich im Autoloader Packages -> Locations und dann Rufen Sie die Datei auf, die für die instanziierte Klasse erforderlich ist.

Dies ist die globale Konfigurationsdatei:

<?php 
    // INITIALIZE GLOBAL Class -> Package map 
    if (!array_key_exists('packageMap',$GLOBALS)) { 
     $GLOBALS['packageMap'] = array(); 
    } 

    spl_autoload_register('my_autoloader'); 

    function my_autoloader($class) { 
     $classMap = array(
      'root'=>'/classes/', 
      'sites'=>'/classes/sites/', 
      'data'=>'/classes/data/' 
     ); 

     // RESOLVE MAPPINGS TO AN ACTUAL LOCATION 
     $classPackage = $GLOBALS['packageMap'][$class]; 
     $location = $classMap[$classPackage]; 
     if (file_exists(__DIR__ . $location . $class . '.php')) { 
      require_once(__DIR__ . $location . $class . '.php'); 
     } 
    } 
?> 

Hier ist eine bestimmte Site-Konfigurationsdatei, die den Autoloader verwendet:

<?php 
    // LOAD GLOBAL CONFIG FILE  
    require_once('../config/init.php'); 

    // CREATE LOCAL REFERENCE TO GLOBAL PACKAGE MAP (MOSTLY FOR READABILITY) 
    $packageMap = $GLOBALS['packageMap']; 

    // ADD Class -> Package MAPPINGS 
    $packageMap['DAO'] = 'data'; 
    $packageMap['SomeSite'] = 'sites'; 
    $packageMap['PDOQuery'] = 'data'; 

    // INSTANTIATE SOMETHING IN ONE OF THE PACKAGES 
    $someSite = new SomeSite(); 
?> 

Hoffentlich ist nützlich, um andere ...Wenn es irgendwelche roten Flaggen für irgendjemanden auslöst, bitte klingeln. Letztendlich möchte ich die Verwendung von $ GLOBALS durch apc ersetzen, aber es ist nicht auf meinem gehosteten Server installiert: /. Ich könnte darüber nachdenken, Memcached, aber ich habe gemischte Bewertungen gehört ...

+0

Sie können auch ['__DIR__'] (http://php.net/manual/en/language.constants.predefined.php) ab PHP 5.3 – Raekye

+0

Ah ja, noch besser ... danke. Lösungscode aktualisiert –

Verwandte Themen