У меня была небольшая проблема с автозагрузкой в моем пространстве имен. Как показано в руководстве по PHP здесь: http://us.php.net/manual/en/language.namespaces.rules.php, вы должны иметь возможность автозагружать функции пространства имен с полным квалифицированным именем, например \ glue \ common \ is_email ( ).
У меня есть функция spl_autoload_register (массив ($ import, "load")); в начальном пространстве имен, но всякий раз, когда я пытаюсь вызвать \ glue \ common \ is_email () из исходного пространства имен, он не будет передавать эту функцию автозагрузки, но при использовании нового is_email () (в контексте класса) он будет. Я не понимаю, что это руководство говорит, что я могу автозагрузить от полностью квалифицированных имен, но я не могу:.
Вот мой код:
namespace glue; require_once 'import.php'; use glue\import as import; use glue\core\router as router; $import = new import(); spl_autoload_register(array($import, "load")); /** Works and echos glue\router **/ $router = new router(); /** Don't do nothing **/ $cheese = \glue\common\is_email($email);
Я также пробовал этот код:
namespace glue; require_once 'import.php'; use glue\import as import; use glue\core\router as router; use glue\common; $import = new import(); spl_autoload_register(array($import, "load")); /** Works and echos glue\router **/ $router = new router(); /** Don't do nothing **/ $cheese = common\is_email($email);
и, наконец, этот код:
namespace glue; require_once 'import.php'; use glue\import as import; use glue\core\router as router; use glue\common\is_email as F; $import = new import(); spl_autoload_register(array($import, "load")); /** Works and echos glue\router **/ $router = new router(); /** Don't do nothing **/ $cheese = F($email);
Вот только правильный ответ.
Каждому пространству имен требуется собственная функция spl_autoload_register ().
также, синтаксис spl_autoload_register (), измененный в 5.3:
spl_autoload_register(__NAMESPACE__ . "\\className::functionName"));
Следующее должно работать:
namespace glue; require_once 'import.php'; use glue\import as import; use glue\core\router as router; $import = new import(); spl_autoload_register(__NAMESPACE__ . "\\$import::load")); /** Works and echos glue\router **/ $router = new router(); /** Don't do nothing **/ $cheese = \glue\common\is_email($email);
Вот какой живой код, который работает!
в ../WebPageConsolidator.inc.php:
class WebPageConsolidator { public function __construct() { echo "PHP 5.2 constructor.\n"; } }
в test.php:
<?php namespace WebPage; class MyAutoloader { public static function load($className) { require '../' . __NAMESPACE__ . $className . '.inc.php'; } } spl_autoload_register(__NAMESPACE__ . "\\MyAutoloader::load"); class Consolidator extends \WebpageConsolidator { public function __construct() { echo "PHP 5.3 constructor.\n"; parent::__construct(); } } // Output: // PHP 5.3 constructor. // PHP 5.2 constructor.
Поэтому я знаю, что это работает.
Заблуждение в вопросе ОП, вероятно, заключается в том, что функции / методы будут подвергнуты автозагрузке, а это не так. Автозагрузка запускается только с помощью ссылок на классы.
При этом остается вопрос об автозагрузке классов в пространствах имен :
По состоянию на 2017 г. существующий стандарт PHP-FIG для автозагрузки – это PSR-4, который предоставляет следующий код автозагрузки для классов с именами:
<?php /** * An example of a project-specific implementation. * * After registering this autoload function with SPL, the following line * would cause the function to attempt to load the \Foo\Bar\Baz\Qux class * from /path/to/project/src/Baz/Qux.php: * * new \Foo\Bar\Baz\Qux; * * @param string $class The fully-qualified class name. * @return void */ spl_autoload_register(function ($class) { // project-specific namespace prefix $prefix = 'Foo\\Bar\\'; // base directory for the namespace prefix $base_dir = __DIR__ . '/src/'; // does the class use the namespace prefix? $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { // no, move to the next registered autoloader return; } // get the relative class name $relative_class = substr($class, $len); // replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // if the file exists, require it if (file_exists($file)) { require $file; } });
Полный текст спецификации можно найти на PSR-4: Автозагрузчик .
Пример кода выше (и другой для автозагрузки из нескольких пространств имен) можно найти в примерах реализации PSR-4 (или GitHub: fig-standards / accepted / PSR-4-autoloader-examples.md ).
Используйте Composer для автоматической загрузки PHP-классов.
Посмотрите, как это сделать в моем недавнем сообщении в блоге: https://enterprise-level-php.com/2017/12/25/the-magic-behind-autoloading-php-files-using-composer.html