Автозагрузчики в PHP – два запуска за раз

Я понимаю, как регистрировать автозагрузчики и даже как их создавать, это не проблема. Как всегда основная проблема: как у вас есть два автопогрузчика, которые работают бок о бок для чего-то вроде:

class project_one_folder_class extends project_two_folder_class{} 

Вы заметите, что дочерний класс принадлежит проекту, который тянется и вызывает родительский класс, который находится в другом проекте.

То, как проекты связаны с двумя классами проекта, всегда видно автозагрузчику, как никогда проектные классы никогда не видны.

Таким образом, я думал об этом, чтобы написать два автозагрузчика и зарегистрировать их, потому что php будет смотреть дальше, а затем на другой. Как бы php, казалось, смотрел только один, а не другой.

как бы вы решили это?

редактировать

Второй проект – родительский, первый проект – дочерний. Это более расширенный вопрос, чем то, что было опубликовано по этому вопросу .

Для лучшего расширения это мой класс.

 class AisisCore_Loader_AutoLoader{ protected static $_instance; public function get_instance(){ if(null == self::$_instance){ self::$_instance = new self(); } return self::$_instance; } public function reset_instance(){ self::$_instance = null; } public function register_auto_loader(){ spl_autoload_register(array($this, 'load_class')); spl_autoload_register(array($this, 'load_child_class')); } public function load_class($class){ $path = str_replace('_', '/', $class); if(file_exists(get_template_directory() . '/' . $path . '.php')){ require_once(get_template_directory() . '/' . $path . '.php'); } } public function load_child_class($class){ $path = str_replace('_', '/', $class); if(file_exists(get_stylesheet_directory() . '/' . $path . '.php')){ require_once(get_stylesheet_directory() . '/' . $path . '.php'); } } } 

В настоящее время этот класс будет загружать все в родительском проекте. Он даже загружает родительские объекты проекта в дочерний проект. Как бы ни один дочерний объект не мог быть загружен с использованием этого класса, поскольку он не найден.

Те, кто знаком с WordPress, сразу скажут, да, потому что у вас есть get_template_directory когда вы хотите get_stylesheet_directory Как всегда – Знание этого – я хочу написать затем два автозагрузчика, один из которых будет загружать объекты дочерних проектов с помощью get_stylesheet_directory а затем тот, который будет загружать родительские объекты через get_stylesheet_directory чтобы:

class project_one_folder_class extends project_two_folder_class{}

работы и нагрузки, без ошибок.

Это немного грубо, но на самом деле вам нужен только один автозагрузчик, который просто проверяет в нескольких каталогах:

 abstract class Hakre_Theme_AutoLoader { public static $directories; public static function init() { // configure paths self::$directories = array( get_template_directory(), // current theme, parent in case of childtheme get_stylesheet_directory(), // current theme, child in case of childtheme ); // please double check if you really need to prepend return spl_autoload_register('Hakre_Theme_AutoLoader::autoload', true, true); } public static function autoload($class) { $filename = str_replace('_', '/', $class) . '.php'; foreach (self::$directories as $directory) { $path = $directory . '/' . $filename; if (is_file($path)) { require($path); return; # leave because the class has been loaded } } } } Hakre_Theme_AutoLoader::init(); ## If you're unsure all worked out properly: var_dump(Hakre_Theme_AutoLoader::$directories); 

Это должно на самом деле это сделать, однако я не тестировал его. См. var_dump , вы можете отлаживать, зарегистрированы ли правильные каталоги или нет. Нет необходимости иметь несколько обратных вызовов только потому, что вы хотите проверить два каталога.

Ну, конечно, вы могли бы просто найти второй путь, когда первые файлы_файлы вернут false – в том же автозагрузчике.

Вы также можете зарегистрировать второй автозагрузчик для второго пути.

PHP docs обращается к этому:

Если необходимо несколько функций автозагрузки, для этого допускается spl_autoload_register() . Он эффективно создает очередь функций автозагрузки и проходит через каждый из них в том порядке, в котором они определены. Напротив, __autoload() может быть определен только один раз.

Отделите процесс автозагрузки!

PHP работает так: в какой-то момент выполнение кода натыкается на ссылку класса, которая еще не загружена. $obj = new project_one_folder_class()

Теперь вызывается зарегистрированная функция автозагрузчика, начиная с первой добавленной (если только те, которые добавлены позже, не используют параметр «preend»).

Первая (и вся последующая) функция автозагрузки получает имя класса, который должен быть загружен. Теперь функция должна решить

  1. Не стоит ли загружать этот класс? Если нет, ничего не делайте, пусть другие функции попытаются загрузить его.
  2. Если эта функция отвечает за загрузку класса, попробуйте составить путь и имя файла из известного имени класса и потребовать этот файл.

Шаг 1 обычно решается путем поиска, если имя класса, которое должно быть загружено, начинается с определенного префикса. В вашем случае автозагрузчик, отвечающий за загрузку классов, начинающихся с «project_one_», НЕ должен пытаться загружать любые другие классы, начиная с чего-то другого.

Шаг 2 выполняется, если автозагрузчик знает, что он должен выполнить автозагрузку. Теперь он преобразует имя класса в относительный путь и имя файла, добавляет базовый каталог, а затем требует файл.

Требование файла, который определяет класс, который расширяет другой класс (или реализует интерфейсы), может затем запускать еще один запуск автозагрузки с любыми еще неизвестными классами. В вашем случае процесс автозагрузки запускается снова с именем класса «project_two_folder_class». Обратите внимание, что первый автозагрузчик для классов «project_one_» будет вызван снова с этим вторым именем класса, но он ничего не должен делать, потому что он не знает, как загрузить эти классы. Это зависит от автозагрузчика, который знает о классах «project_two_».

Порядок регистрации не должен иметь значения для разных автозагрузчиков. Если это произойдет, автозагрузчики ошибочно работают.

Поскольку обычный шаблон просто преобразует символы подчеркивания в именах классов в DIRECTORY_SEPARATOR, а также обратную косую черту из пространств имен, добавьте в конец «.php», а затем попытайтесь загрузить этот файл из определенного базового каталога, код для двух из этих автозагрузчиков будет одинаковым, и проблема сводится к настройке только одной функции автозагрузки с этими двумя случаями: какой префикс должен присутствовать и в каком базовом каталоге должен быть указан файл, при условии, что имя класса может преобразуется в относительный путь к файлу.

Проверка в каждом случае, существует ли файл в определенном каталоге или нет, не является оптимальной для производительности. Вы в конечном итоге проведете множество проверок файлов, которые вы сможете узнать, что вы не можете загрузить, просто глядя на имя класса.

И, кстати, функции автозагрузчика не обязательно должны быть одиночными. Фактически, ваша реализация singleton нарушена и бесполезна. Перенесите автозагрузчик с помощью new , возможно, передайте некоторые значения конфигурации в конструктор и вызовите spl_autoload_register() , и вы должны сделать это.

Вы можете добавить более одного загрузчика, просто зарегистрируйте каждую функцию с помощью spl_autoload_register ().

процедурный стиль:

 spl_autoload_register('loader_function1')); // your second class location spl_autoload_register('loader_function2')); 

или в стиле OO

 spl_autoload_register(array($this, 'loader_function1')); spl_autoload_register(array($this, 'loader_function2')); 

Однако исходя из вашего вопроса: вы, вероятно, можете сделать то же самое, имея более гибкий автозагрузчик, чтобы увидеть мой ответ в другом вопросе здесь: Класс автозагрузчика в плагине wordpress