2013-03-27 97 views
8

有這個自動加載類自動加載classes最初,但現在我想自動載入interfacesabstracts爲好。PHP:我怎樣自動加載接口和摘要

所以我做了以下這個answer變化,

$reflection = new ReflectionClass($class_name); 

# Return boolean if it is an interface. 
if ($reflection->isInterface()) 
{ 
    $file_name = 'interface_'.strtolower(array_pop($file_pieces)).'.php'; 
} 
else 
{ 
    $file_name = 'class_'.strtolower(array_pop($file_pieces)).'.php'; 

} 

我測試,但這個自動加載類不加載所有接口。任何想法,我已經錯過了?

舉例來說,這是我的接口文件,

interface_methods.php 

及其內容,

interface methods 
{ 
    public function delete(); 
} 

下面是我整個這個自動加載類。

class autoloader 
{ 
    /** 
    * Set the property. 
    */ 
    public $directory; 
    public $recursive; 

    public function __construct($directory, $recursive = array('search' => 'models')) 
    { 
     # Store the data into the property. 
     $this->directory = $directory; 
     $this->recursive = $recursive; 

     # When using spl_autoload_register() with class methods, it might seem that it can use only public methods, though it can use private/protected methods as well, if registered from inside the class: 
     spl_autoload_register(array($this,'get_class')); 
    } 

    private function get_class($class_name) 
    { 
     # List all the class directories in the array. 
     if ($this->recursive) 
     { 
      $array_directories = self::get_recursive_directory($this->directory); 
     } 
     else 
     { 
      if (is_array($this->directory)) $array_directories = $this->directory; 
      else $array_directories = array($this->directory); 
     } 

     # Determine the class is an interface. 
     $reflection = new ReflectionClass($class_name); 

     $file_pieces = explode('\\', $class_name); 

     # Return boolean if it is an interface. 
     if ($reflection->isInterface()) 
     { 
      $file_name = 'interface_'.strtolower(array_pop($file_pieces)).'.php'; 
     } 
     else 
     { 
      $file_name = 'class_'.strtolower(array_pop($file_pieces)).'.php'; 

     } 

     # Loop the array. 
     foreach($array_directories as $path_directory) 
     { 
      if(file_exists($path_directory.$file_name)) 
      { 
       include $path_directory.$file_name; 
      } 
     } 

    } 

    public function get_recursive_directory($directory) 
    { 
     $iterator = new RecursiveIteratorIterator 
        (
         new RecursiveDirectoryIterator($directory), 
         RecursiveIteratorIterator::CHILD_FIRST 
        ); 

     # This will hold the result. 
     $result = array(); 

     # Loop the directory contents. 
     foreach ($iterator as $path) 
     { 

      # If object is a directory and matches the search term ('models')... 
      if ($path->isDir() && $path->getBasename() === $this->recursive['search']) 
      { 

       # Add it to the result array. 
       # Must replace the slash in the class - dunno why! 
       $result[] = str_replace('\\', '/', $path).'/'; 
       //$result[] = (string) $path . '/'; 

      } 

     } 

     # Return the result in an array. 
     return $result; 
    } 
} 
+0

也許我錯過了一些東西,但是如何在尚未(自動)加載的類/接口上使用'ReflectionClass'? – Uby 2013-03-27 20:58:18

+0

你是對的。也許我不應該在autoload類中使用'ReflectionClass'。但我怎樣才能自動加載接口和摘要是主要問題。 – laukok 2013-03-27 21:01:47

+2

由於它是自動加載的,你不能使用反射,你應該通過類/接口名稱「猜測」文件的位置。通常命名約定是解決方案。 PRS-0可能是您的一個選擇:https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md – Uby 2013-03-27 21:07:43

回答

10

PHP在任何類或接口或抽象類之間沒有區別。您定義的自動加載器功能總是獲取要自動加載的東西的名稱,並且沒有提示它是哪一種。

因此,您的命名策略不能自動加載,因爲您將界面與「interface_」和具有「class_」的類相加。就我個人而言,我覺得這樣的命名習慣很煩人。

另一方面,您的自動加載器完全不能正常工作。它會遞歸地掃描整個目錄樹,以找到一個類!下一個班級必須再次做所有的工作,而沒有以前做過的好處!

如果你真的想自己做(而不是使用像composer這樣的東西來爲你做),請執行PSR-0自動加載器,並堅持這種類和接口的命名方案。

請選擇一個區分的類名稱前綴或名稱空間,並且作爲第一步檢查您的自動裝載器中,如果要加載的類具有此前綴。如果沒有,立即返回。這使您不必旋轉硬盤並查看該類的文件名是否存在。

如果前綴不匹配,它不是你想要加載的類,所以你的自動加載器不知道該怎麼做,甚至不應該嘗試,但是已經註冊的不同的自動加載器會知道。