我有这个自动加载器类最初自动加载类,但现在我想自动加载接口和摘要.
所以我在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; } }
PHP在任何类或接口或抽象类之间没有区别.您定义的自动加载器功能总是获取自动加载的东西的名称,并且没有提示它是哪一个.
因此,您的命名策略无法自动加载,因为前缀接口为“interface_”,类为“class_”.就个人而言,我发现这样的命名约定相当烦人.
另一方面,您的自动加载器完全无法使用.它递归扫描整个目录树只是为了找到一个类!接下来的课程必须再次完成所有的工作,而不必事先做好!
如果你真的想自己做(而不是像composer那样为你做这件事),请实现PSR-0自动加载器,并坚持这种类和接口的命名方案.
请选择一个可区分的类名前缀或命名空间,并作为第一步检查自动装带器内是否要加载的类具有此前缀.如果没有,立即返回.这使您不必旋转硬盘并查看该类的文件名是否存在.
如果前缀不匹配,则不是“你的”类要加载,因此您的自动加载器无法知道如何操作,甚至不应该尝试,但已注册的其他自动加载器将知道.