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