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