Поведение пространства имен PHP дает ФАТАЛЬНУЮ ошибку с spl_autoload_register

Я хочу использовать пространство имен и spl_autoload_register вместе, но каждый раз с ошибкой.

См. полные файлы кода на github.

Ниже находятся файлы

  1. базовый файл, в котором создается класс с пространством имен class.alpha.php
  2. включаемый файл, в котором я определяю spl_autoload_register include.php
  3. пример файла, который создает экземпляр объекта класса eg.php

Теперь, когда я создаю объект из eg.php, он выдает ФАТАЛЬНУЮ ошибку, но когда я комментирую строку пространства имен в class.alpha.php, он работает

Пожалуйста, смотрите код ниже.

alpha.class.php

<?php
//namespace Alpha; //<< comment and uncomment this to regenerate the error

class Alpha
{
    // public static $baseDir_;
    public $dir = __DIR__;
    public static $baseDir_;
    public function __construct()
    {
        echo __FILE__."=>".__METHOD__;
        var_dump(self::$baseDir_, $this->dir);
        $firstDir = !empty(self::$baseDir_) ? self::$baseDir_ :  $this->dir;
    }
}

include.php

<?php //namespace Alpha\config;
spl_autoload_extensions(".php");
spl_autoload_register('loadclass');

function loadclass($class)
{
    try {
        if (is_readable(strtolower($class).".class.php")) {
            include_once strtolower($class).".class.php";
        }
    } catch (Exception $e) {
        print "Exception:". $e;           
    }
}
//@link http://php.net/manual/en/function.spl-autoload-register.php
// spl_autoload_register(__NAMESPACE__.'Alpha\Alpha()' );

например.php

<?php
require_once 'include.php';

/** below code works by commenting 1st line on alpha.class.php 
if we un comment then below code gives Fatal error: Class 'Alpha' not found */
Alpha::$baseDir_ = '/opt/lampp/archive/';
$obj_ = new Alpha();
var_dump(get_included_files());
var_dump($obj_);

/** now we define namespace Alpha on alpha.class.php */
// $ns_ = new Alpha\Alpha(); // Fatal error: Class 'Alpha\Alpha' not found
// var_dump($ns_);

/** not working even with use statement */
// use Alpha;
// use Alpha;
// $fn = new Alpha\Alpha();
// var_dump($fn);

Пожалуйста, помогите мне решить эту проблему.

Спасибо


person diEcho    schedule 22.01.2015    source источник


Ответы (1)


Ваш автозагрузчик получает запрос на класс «Альфа\Альфа», если вы раскомментируете пространство имен в alpha.class.php и поместите use Alpha\Alpha, например. Это означает, что место, где он ожидает найти ваш класс, будет alpha\alpha.class.php.

Если вы не работаете в Windows, разделители каталогов обычно представляют собой косую черту (/). Итак, есть несколько возможных решений.

**Возможное решение №1. Оставьте все файлы в одном месте**

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

$classParts = explode("\\", $class);
$class = $classParts[count($classParts) - 1];

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

Возможное решение 2. Разместите пространства имен в подкаталогах

Для этого решения вы должны создать новый каталог «alpha» и переместить в него «alpha.class.php». Для изменения автозагрузчика вы можете добавить следующие строки в начало вашего автозагрузчика:

$class = str_replace("\\", "/", $class);

Это изменит разделители пространств имен с обратной косой черты на разделители путей к файлам с прямой косой чертой. Это будет работать на Windows, а также на Mac и Linux.

Возможное решение №3. Следуйте установленному стандарту автозагрузки

Уже существует ряд стандартных стандартов автозагрузки PHP. PSR-0 (теперь устаревший) работает, но рекомендуется PSR-4:

Одним из больших преимуществ следования одному из этих стандартов является то, что для них уже существует множество реализаций, и было много размышлений о том, как они должны работать и поддерживать совместимость с другими библиотеками, которые вы, возможно, захотите использовать. Composer (http://getcomposer.org) позволит вам настроить и использовать стиль PSR-0 и PSR-4. автозагрузчики на основе очень простой конфигурации.

В любом случае, для толпы TL; DR проблема заключается в том, что автозагрузчик получает весь путь в пространстве имен, чтобы знать, как загрузить класс. Неустранимая ошибка заключалась в том, что автозагрузчик неправильно отображал этот класс с пространством имен на расположение в файловой системе, поэтому файл, содержащий класс, никогда не загружался.

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

person David Stockton    schedule 15.05.2015
comment
Спасибо за ответ. обязательно рассмотрю предложения - person diEcho; 22.05.2015