Как использовать пространства имен PHP с автозагрузкой?

Я получаю эту ошибку, когда пытаюсь использовать autoload и namespaces:

Неустранимая ошибка: Class 'Class1' не найден в /usr/local/www/apache22/data/public/php5.3/test.php в строке 10

Может ли кто-нибудь сказать мне, что я делаю неправильно?

Вот мой код:

Class1.php:

<?php namespace Person\Barnes\David { class Class1 { public function __construct() { echo __CLASS__; } } } ?> 

test.php:

 <?php function __autoload($class) { require $class . '.php'; } use Person\Barnes\David; $class = new Class1(); ?> 

Solutions Collecting From Web of "Как использовать пространства имен PHP с автозагрузкой?"

Класс1 не входит в глобальную область.

Ниже приведен рабочий пример:

 <?php function __autoload($class) { $parts = explode('\\', $class); require end($parts) . '.php'; } use Person\Barnes\David as MyPerson; $class = new MyPerson\Class1(); 

Редактировать (2009-12-14):

Просто для уточнения, мое использование «use … as» было упростить пример.

Альтернативой было следующее:

 $class = new Person\Barnes\David\Class1(); 

или

 use Person\Barnes\David\Class1; // ... $class = new Class1(); 

Как уже упоминалось, Паскаль МАРТИН, вы должны заменить '\' на DIRECTORY_SEPARATOR, например:

 $filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; include($filename); 

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

Структура каталога:

 ProjectRoot |- lib 

Файл: /ProjectRoot/lib/Person/Barnes/David/Class1.php

 <?php namespace Person\Barnes\David class Class1 { public function __construct() { echo __CLASS__; } } ?> 
  • Создайте подкаталог для каждого пространства имен, которое вы определили.

Файл: /ProjectRoot/test.php

 define('BASE_PATH', realpath(dirname(__FILE__))); function my_autoloader($class) { $filename = BASE_PATH . '/lib/' . str_replace('\\', '/', $class) . '.php'; include($filename); } spl_autoload_register('my_autoloader'); use Person\Barnes\David as MyPerson; $class = new MyPerson\Class1(); 
  • Я использовал рекомендацию php 5 для объявления автозагрузчика. Если вы все еще используете PHP 4, замените его на старый синтаксис: function __autoload ($ class)

Ваша функция __autoload получит полное имя класса, включая имя пространства имен.

Это означает, что в вашем случае функция __autoload получит « Person\Barnes\David\Class1 », а не только « Class1 ».

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

Я делаю что-то вроде этого:

 spl_autoload_register('AutoLoader'); function AutoLoader($className) { $file = str_replace('\\',DIRECTORY_SEPARATOR,$className); require_once 'classes' . DIRECTORY_SEPARATOR . $file . '.php'; //Make your own path, Might need to use Magics like ___DIR___ } 

Я нашел этот камень от Flysystem

 spl_autoload_register(function($class) { $prefix = 'League\\Flysystem\\'; if ( ! substr($class, 0, 17) === $prefix) { return; } $class = substr($class, strlen($prefix)); $location = __DIR__ . 'path/to/flysystem/src/' . str_replace('\\', '/', $class) . '.php'; if (is_file($location)) { require_once($location); } }); 

Я вижу, что функции автозагрузки получают только «полное» имя класса – со всеми пробелами, предшествующими им, – в следующих двух случаях:

 [a] $a = new The\Full\Namespace\CoolClass(); [b] use The\Full\Namespace as SomeNamespace; (at the top of your source file) followed by $a = new SomeNamespace\CoolClass(); 

Я вижу, что функции автозагрузки НЕ получают полное имя класса в следующем случае:

 [c] use The\Full\Namespace; (at the top of your source file) followed by $a = new CoolClass(); 

ОБНОВЛЕНИЕ: [c] является ошибкой, а не тем, как пространства имен работают в любом случае. Я могу сообщить, что вместо [c] также работают следующие два случая:

 [d] use The\Full\Namespace; (at the top of your source file) followed by $a = new Namespace\CoolClass(); [e] use The\Full\Namespace\CoolClass; (at the top of your source file) followed by $a = new CoolClass(); 

Надеюсь это поможет.

имел такую ​​же проблему и только что нашел это:

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

  spl_autoload_extensions(".php"); // comma-separated list spl_autoload_register(); 

Оно работало завораживающе

Подробнее здесь: http://www.php.net/manual/en/function.spl-autoload-register.php#92514

EDIT: это вызывает проблемы в Linux из-за обратной косой черты … См. Здесь для рабочего решения от immeëmosol

Пространство имен Autoload работает под окнами, но не в Linux

Использование имеет gotcha, в то время как это самый быстрый способ, он также ожидает, что все ваши имена файлов будут строчными.

 spl_autoload_extensions(".php"); spl_autoload_register(); 

Например:

Файл, содержащий класс SomeSuperClass, должен быть назван somesuperclass.php, это будет получение при использовании чувствительной к регистру файловой системы, такой как Linux, если ваш файл называется SomeSuperClass.php, но не проблема в Windows.

Использование __autoload в вашем коде может по-прежнему работать с текущими версиями PHP, но ожидайте, что эта функция станет устаревшей и, наконец, удалена в будущем.

Итак, какие варианты остались:

Эта версия будет работать с PHP 5.3 и выше и допускает имена файлов SomeSuperClass.php и somesuperclass.php. Если вы используете 5.3.2 и выше, этот автозагрузчик будет работать еще быстрее.

 <?php if ( function_exists ( 'stream_resolve_include_path' ) == false ) { function stream_resolve_include_path ( $filename ) { $paths = explode ( PATH_SEPARATOR, get_include_path () ); foreach ( $paths as $path ) { $path = realpath ( $path . PATH_SEPARATOR . $filename ); if ( $path ) { return $path; } } return false; } } spl_autoload_register ( function ( $className, $fileExtensions = null ) { $className = str_replace ( '_', '/', $className ); $className = str_replace ( '\\', '/', $className ); $file = stream_resolve_include_path ( $className . '.php' ); if ( $file === false ) { $file = stream_resolve_include_path ( strtolower ( $className . '.php' ) ); } if ( $file !== false ) { include $file; return true; } return false; }); 

Я запишу свои два цента для относительных новичков или не хочу простой установки spl_autoload_register () без всякой теории: просто создайте один файл php для каждого класса, назовите php-файл таким же, как имя вашего класса, и сохраните файлы классов в том же каталоге, что и ваш php-файл, это будет работать:

 spl_autoload_register(function ($class_name) { require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $class_name . '.php'; }); 

Разбивание частей внутри этой функции должно отвечать на вопрос, как это работает. PS: Я использую Linux, и это работает на Linux. Сначала люди Windows должны проверить это.

https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/

Вы хотите поместить свои файлы классов в папку с именем Classes, которая находится в том же каталоге, что и точка входа в ваше PHP-приложение. Если классы используют пространства имен, пространства имен будут преобразованы в структуру каталогов. В отличие от многих других автозагрузчиков, символы подчеркивания не будут преобразованы в структуры каталогов (сложно сделать PHP <5.3 псевдопространств имен вместе с PHP> = 5.3 реальными пространствами имен).

 <?php class Autoloader { static public function loader($className) { $filename = "Classes/" . str_replace("\\", '/', $className) . ".php"; if (file_exists($filename)) { include($filename); if (class_exists($className)) { return TRUE; } } return FALSE; } } spl_autoload_register('Autoloader::loader'); 

Вы захотите поместить следующий код в свой основной скрипт PHP (точка входа):

 require_once("Classes/Autoloader.php"); 

Вот пример макета каталога:

 index.php Classes/ Autoloader.php ClassA.php - class ClassA {} ClassB.php - class ClassB {} Business/ ClassC.php - namespace Business classC {} Deeper/ ClassD.php - namespace BusinessDeeper classD {} 

Недавно я нашел ответ tanerkuc очень полезным! Просто хотелось добавить, что использование strrpos() + substr() немного быстрее, чем explode() + end() :

 spl_autoload_register( function( $class ) { $pos = strrpos( $class, '\\' ); include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php'; });