PHP: как автоматически загружать интерфейсы и тезисы
У меня есть этот класс автозагрузки для автозагрузки classes
изначально, но теперь хочу автозагрузку interfaces
а также abstracts
также.
Поэтому я внес изменения после этого ответа,
$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;
}
}
1 ответ
PHP не делает различий между классом, интерфейсом или абстрактным классом. Функция автозагрузчика, которую вы определяете, всегда получает имя вещи для автозагрузки, и не указывает на то, какой она была.
Таким образом, ваша стратегия именования не может быть автоматически загружена, потому что вы добавляете интерфейсы к "interface_", а классы к "class_". Лично я нахожу такое соглашение об именах довольно раздражающим.
С другой стороны, ваш автозагрузчик совершенно не работает. Он рекурсивно сканирует целые деревья каталогов, чтобы найти один класс! И следующий класс должен снова выполнить всю работу, не имея возможности сделать это раньше!
Пожалуйста, внедрите автозагрузчик PSR-0, если вы действительно хотите сделать это самостоятельно (и не используйте такие вещи, как composer, чтобы сделать это за вас) и придерживайтесь этой схемы именования для классов и интерфейсов.
И, пожалуйста, выберите отличительный префикс имени класса или пространство имен, и в качестве первого шага проверьте в своем автозагрузчике, имеет ли префикс загружаемый класс. Вернитесь немедленно, если это не так. Это освобождает вас от необходимости вращать жесткий диск и видеть, существует ли имя файла для класса.
Если префикс не совпадает, это не "ваш" класс, который хочет быть загруженным, поэтому ваш автозагрузчик не может знать, как это сделать, и не должен даже пытаться, но другой зарегистрированный автозагрузчик будет знать.