2013-07-23 13 views
5

Eksperymentowałem z technikami mapowania katalogu klasy autoloadera, i to było trochę walki. Udało mi się znaleźć dość proste rozwiązanie (na powierzchni), ale jestem całkowicie zaskoczony, że działa w ogóle, podczas gdy inne "bardziej oczywiste" rozwiązania zawiodły. Poniżej znajduje się kilka fragmentów kodu, które ilustrują moje zamieszanie.autoloader php: dlaczego to działa?

Oto kod roboczych:

<?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; 
      } 
     } 
    } 
?> 

Oto urywek że czułem powinien pracy, ale nie:

<?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'); 
      } 
     } 
    } 
?> 

Ten ostatni ma większy sens dla mnie, bo gdy te dwa wersje działają:

<?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'); 
    } 
?> 

Ten jeden wyrzuca "Brak takiego pliku lub katalogu ..." (zwróć uwagę na brak "sites /" w ścieżce.

<?php 
    spl_autoload_register('my_autoloader'); 

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

„nie ma takiego pliku lub katalogu ...” Błąd uświadomiła mi, że mogę po prostu sprawdzić plik nośnej klasy i, jeśli (file_exists()) {require_once(); break;} else {continue;}

Dlaczego to nie działa? I dlaczego działa pierwszy snippet? Ścieżka/plik pomocniczy nigdy nie jest wyraźnie zawarty ani wymagany.

+0

to katalog nadrzędny ścieżki klas w twoich ścieżkach include_paths? – Orangepill

+0

Dołączony jest plik pomocniczy, jest on połączony z instrukcją if: if (! @include_once ($ location. $ Class. '.php')) –

+0

Tak, myślałem o tym, john500, ale liczyłem na potwierdzenie , dzięki za to. Czuję się jak bardzo niechlujny sposób, aby osiągnąć to, czego potrzebuję, więc to po prostu podrażnia moją świnkę, by ulepszyć rozwiązanie. Orangepill, nie jestem pewien, jak to zrobić ... Nie pracowałem z PHP przez jakiś czas, a kiedy ostatnio to zrobiłem, nie byłem w połowie tak dobry w programowaniu jak teraz ... więc "Zasadniczo hackowanie w PHP próbuje robić rzeczy, które już wiem jak robić w Javie i ColdFusion;). –

Odpowiedz

1

OK, wymyśliłem to. Mój problem faktycznie nie ustawiał ścieżki poprawnie; używanie stałej __DIR__ było ścieżką :: ahem :: success. Oto kod roboczych Obecnie używam:

<?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; 
      } 
     } 
    } 
?> 

Okazuje się __DIR__ zwraca lokalizację katalogu rzeczywistego pliku, w którym jest nazywany (w przeciwieństwie do, powiedzmy, plik, który jest w tym to), który oznacza, że ​​będzie działać tak długo, dopóki plik ten pozostanie w katalogu głównym katalogu my/classes. I istnieje wyłącznie w celu zdefiniowania tego rodzaju ustawień ...

Mam nadzieję, że pomoże to komuś innemu na linii! I, oczywiście, jeśli ktoś może rzucić światło na dlaczego to rozwiązanie jest nieoptymalne, jestem wszystkie oczy ...

EDIT: Jeden optymalizacji będę wykonywać będzie przekonwertować tablicę $ classMap() do tablicy asocjacyjnej (np ,. $classMap = array('root' => 'classes/', 'sites' => 'classes/sites/'); więc mogę zrobić odnośnika zamiast pętli wszystkich katalogach tworzę z czasem Ale sądzę, że to dla innego wątku

Edit2.. Jeśli ktoś jest zainteresowany, oto rozwiązanie wymyśliłem to jako tablicę asocjacyjną.Zasadniczo skonfigurowałem tablicę asocjacyjną w $ GLOBALS i używam jej do przechowywania mapy klas -> Pakiety, a następnie w autoloaderzie mapuję pakiety -> Lokalizacje i następnie wywołaj plik niezbędny do utworzenia instancji klasy.

Jest to globalny plik konfiguracyjny:

<?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'); 
     } 
    } 
?> 

Oto konkretny obiekt plik konfiguracyjny, który używa autoloadery:

<?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(); 
?> 

Mam nadzieję, że jest to przydatne dla innych ...jeśli wzniesie dla wszystkich jakąś czerwoną flagę, zadzwoń. Ostatecznie chciałbym zastąpić użycie $ GLOBALS przez apc, ale nie jest on zainstalowany na moim hostowanym serwerze: /. Mogę wziąć pod uwagę memcached, ale słyszałem mieszane recenzje ...

+0

Możesz również użyć ['__DIR__'] (http://php.net/manual/en/language.constants.predefined.php) od PHP 5.3 – Raekye

+0

Ach tak, jeszcze lepiej ... dzięki. Zaktualizowano kod rozwiązania. –

Powiązane problemy