__autoload обнаруживает и включает интерфейсы

Я использую __autoload в своем сценарии для включения классов по мере необходимости. Мой сценарий использует подсказки в имени класса, чтобы найти файл, содержащий его. Если он заканчивается на model, он находится в каталоге модели, контроллеры находятся в каталоге контроллера и т. д. Я начинаю реализовывать интерфейсы, поэтому мне нужно настроить автозагрузчик.

В идеале, когда объект создается, автозагрузчик определяет имя файла объекта, где он хранится, и включает файл. Затем он запросит у этого класса, какие интерфейсы он реализует, а затем автоматически включит эти файлы.

Что-то вроде

function __autoload($classname){
    echo $classname;
    include ("classes/$classname.php");
    $interfaces = class_implements($classname,FALSE);
    foreach($interfaces as $name){
        if(!class_exists($name,FALSE)){
        include("interfaces/".$name."inter.php");
        }
    }
}

За исключением случаев, когда я это делаю, я получаю сообщение об ошибке

Невозможно повторно объявить __autoload() (ранее объявленный в W:\xampp\htdocs\test\auto.php:5) в W:\xampp\htdocs\test\auto.php в строке 11.

нельзя ли сделать это в __autoload()? Должен ли я просто продолжать полагаться на соглашения об именах, чтобы различать типы объектов и места их хранения?


person Tyson of the Northwest    schedule 25.08.2011    source источник
comment
Примечание: взгляните на стандарт PSR-0 groups.google.com/group/php-standards/web/psr-0-final-proposal   -  person KingCrunch    schedule 25.08.2011


Ответы (3)


Вы не можете определить класс до того, как будут определены реализованные интерфейсы, и любой дополнительный неизвестный интерфейс также вызовет функцию автозагрузки. Это означает, что в строке 3 при включении класса будет запущена функция автозагрузки снова с интерфейсами как $classname. Теперь при возврате из второго __autoload()-вызова он попытается еще раз включить интерфейсы, что не удастся из-за "уже определенных".

Дополнительно: использование __autoload() не рекомендуется при использовании spl_autoload_register().

person KingCrunch    schedule 25.08.2011

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

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

Это не сработает таким образом. Смотрите умный ответ KingCrunch.

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

person GolezTrol    schedule 25.08.2011

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

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

function __autoload($classname) {
    $classlist=array('MyClass1','path/to/file/myclass1.php',
                          'MyClass2','path/to/file/foo.php',
...
                         );

    $interfacelist=array('MyInterface1','path/to/file/bar1.php',
                              'I_foo','path/to/file/bibble.php',
...
                         );
            $path=$classname;
            if(array_key_exists($classname,$classlist)) {
                $path=PATH_CLASSES.$classlist[$classname];
            } else if(array_key_exists($classname,$interfacelist)) {
                $path=PATH_INTERFACES.$interfacelist[$classname];
            }
            if(file_exists($path)) {
                require_once($path);
            } else {
                $e=new Exception("Problem with path: $path");
            }
}
person dnagirl    schedule 25.08.2011