Ответ 1
Автозагрузчик SPL чрезвычайно примитивен - он не знает пространства имен, поэтому он пытается загрузить файл с именем \in it, а в Linux/Unix - разделитель путей/не.
У меня есть следующий php-код:
index.php
<?php
spl_autoload_extensions(".php");
spl_autoload_register();
use modules\standard as std;
$handler = new std\handler();
$handler->delegate();
?>
модули\стандарт\handler.php
<?php
namespace modules\standard {
class handler {
function delegate(){
echo 'Hello from delegation!';
}
}
}
?>
В Windows 7, запущенной WAMP, код выдает сообщение "Привет от делегирования!". однако под Linux я получаю следующее:
Неустранимая ошибка: spl_autoload(): Модули классов\standard\обработчик не могут быть загружены в /var/www/index.php в строке 15
Windows работает под управлением PHP 5.3.0 под WAMP, а Linux работает с пакетом 5.3.2 dotdeb под Ubuntu 9.10.
Является ли это проблемой конфигурации в моем Linux-модуле или просто отличается тем, как пространства имен и автозагрузка обрабатываются в разных операционных системах.
Автозагрузчик SPL чрезвычайно примитивен - он не знает пространства имен, поэтому он пытается загрузить файл с именем \in it, а в Linux/Unix - разделитель путей/не.
Герман Радтке говорит, что он отправил патч:
http://www.hermanradtke.com/blog/hidden-features-with-spl_autoload-and-namespaces/
: S
Я надеюсь, что это будет реализовано в ближайшее время.
Теперь я использую это обходное решение:
<?php
set_include_path( './classes/' . PATH_SEPARATOR . get_include_path() );
spl_autoload_extensions( '.php , .class.php' );
spl_autoload_register();
function linux_namespaces_autoload ( $class_name )
{
/* use if you need to lowercase first char *
$class_name = implode( DIRECTORY_SEPARATOR , array_map( 'lcfirst' , explode( '\\' , $class_name ) ) );/* else just use the following : */
$class_name = implode( DIRECTORY_SEPARATOR , explode( '\\' , $class_name ) );
static $extensions = array();
if ( empty($extensions ) )
{
$extensions = array_map( 'trim' , explode( ',' , spl_autoload_extensions() ) );
}
static $include_paths = array();
if ( empty( $include_paths ) )
{
$include_paths = explode( PATH_SEPARATOR , get_include_path() );
}
foreach ( $include_paths as $path )
{
$path .= ( DIRECTORY_SEPARATOR !== $path[ strlen( $path ) - 1 ] ) ? DIRECTORY_SEPARATOR : '';
foreach ( $extensions as $extension )
{
$file = $path . $class_name . $extension;
if ( file_exists( $file ) && is_readable( $file ) )
{
require $file;
return;
}
}
}
throw new Exception( _( 'class ' . $class_name . ' could not be found.' ) );
}
spl_autoload_register( 'linux_namespaces_autoload' , TRUE , FALSE );
?>
function __autoload($class_name) {
$paths[] = dirname(__FILE__) . "/../libs/misc/";
$paths[] = dirname(__FILE__) . "/../../libs/misc/";
$paths[] = dirname(__FILE__) . "/../../libs/helpers/";
$paths[] = dirname(__FILE__) . "/../../libs/simpleimage/";
foreach($paths as $path)
{
if(file_exists($path.strtolower($class_name).'.class.php')){
require_once($path.strtolower($class_name).'.class.php');
}
}
}
function __autoload($class_name)
{
$class_name = strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $class_name));
include $class_name . '.php';
}
В Apache требуется srttolower
, потому что это (в отличие от IIS) случайный.
Это обычная проблема возникает при автозагрузке. Исправление состоит в использовании константы DIRECTORY_SEPARATOR в функции автозагрузки.
Таким образом, ваша функция автозагрузки будет выглядеть следующим образом
<?php
spl_autoload_register(function($className) {
$className = str_replace("\", DIRECTORY_SEPARATOR, $className);
include_once $_SERVER['DOCUMENT_ROOT'] . '/class/' . $className . '.php';
});
Если вам нужно больше узнать об автозагрузке пространства имен/класса, посетите здесь
Спасибо.