__autoload обнаружение и включая интерфейсы - PullRequest
3 голосов
/ 25 августа 2011

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

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

Что-то вроде

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 ()?Должен ли я просто продолжать полагаться на соглашения об именах, чтобы различать типы объектов и место их хранения?

Ответы [ 3 ]

7 голосов
/ 25 августа 2011

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

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

4 голосов
/ 25 августа 2011

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

[править]

Так не будет.См. Умный ответ KingCrunch.

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

2 голосов
/ 25 августа 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");
            }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...