2013-07-23 29 views
5

我一直在嘗試使用自動加載器的類目錄映射技術,這已經有點困難了。我試圖想出一個相當簡單的解決方案(表面上),但我完全不知道它可以工作,而其他「更明顯」的解決方案卻失敗了。下面是一些代碼片段,說明了我的困惑。php自動加載器:爲什麼這個工作?

這裏的工作代碼:

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

這裏的,我覺得應該工作的摘要,但不會:

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

後者更有意義,我因爲在這兩個版本工作:

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

This one throws 「沒有這樣的文件或目錄...」(注意路徑中缺少「網站/」。

<?php 
    spl_autoload_register('my_autoloader'); 

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

的「沒有這樣的文件或目錄...」錯誤讓我覺得我可以簡單地檢查一類的支持文件,如果(file_exists()){require_once(); break;} else {continue;}

爲什麼不行?而且,爲什麼第一個片段能夠工作?支持路徑/文件從未明確包含或不需要。

+0

是include_paths中類路徑的父目錄嗎? – Orangepill

+0

包括的支持文件,它只是合併到if語句中:if(!@include_once($ location。$ class。'.php')) –

+0

是的,我有點想,john500,但希望確認,非常感謝。儘管如此,這感覺就像是一種非常sl way的方式,所以這只是使我的癢感改善了解決方案。我不知道該怎麼做......我一段時間都沒有和PHP一起工作,而當我上一次做的時候,我的編程和現在一樣不是我的一半......所以我基本上黑客攻擊PHP試圖做我已經知道如何在Java和ColdFusion中做的事情;)。 –

回答

1

好的,我想通了。我的問題確實沒有正確設定路徑;使用__DIR__常數是:: ahem ::成功的途徑。下面是我現在正在使用的工作代碼:

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

原來__DIR__返回調用它的實際文件的目錄位置(而不是,說了,就是包括它的文件),其中這意味着只要該文件保留在我的/ classes目錄下的目錄根目錄下,就可以工作。而且,它僅用於定義這些設置...

希望這可以幫助別人下線!當然,如果任何人都可以解釋爲什麼這個解決方案是次優的,我所有的眼睛......

編輯:我將執行一個優化將轉換$ classMap數組()關聯數組(例如,。$classMap = array('root' => 'classes/', 'sites' => 'classes/sites/');所以我可以做一個查詢,而不是遍歷所有我創建隨着時間的推移目錄不過,我想這是另一個線程

EDIT2:如果任何人的興趣,這裏的我基本上在$ GLOBALS中設置了一個關聯數組,然後用它來存儲Classes - > Packages的映射,然後在自動加載器中映射Packages - > Locations和然後調用實例化類所需的文件。

這是全局配置文件:

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

下面是一個使用自動加載磁帶機特定站點的配置文件:

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

希望這是有用的人......如果它爲任何人提出任何紅旗,請加入。最終,我想用apc替換$ GLOBALS的使用,但它未安裝在我的託管服務器上:/。我可能會考慮memcached,但我聽說過複雜的評論...

+0

你也可以使用['__DIR__'](http://php.net/manual/en/language.constants.predefined.php)從PHP 5.3開始 – Raekye

+0

啊,是的,甚至更好......謝謝。解決方案代碼更新 –