Есть ли способ использовать CLASS_EXISTS и __autoload без CRASH скрипта? - PullRequest
10 голосов
/ 28 сентября 2010

Пример:

ClassName.php

<?php echo "This will crash all"; ?>

В другом файле ...

foreach ($FILENAMES_WITHOUT_DOT_PHP as $name => $value) {
    if (class_exists( $value )) {
      echo "ClassName exists...";
    }
    else {
      echo "ClassName doesn't exists....";
    }
}

Вывод этого кода: Это приведет к краху всех

Вместо этого: ClassName не существует ....

Функция автозагрузки:

function __autoload( $var_class )
{
     require_once( "$var_class.php") ;
}

Ответы [ 4 ]

12 голосов
/ 28 сентября 2010

Хорошо, вот как это работает внутри.

Когда вы пытаетесь использовать класс, который не существует, он вызывает каждый из spl_autoload обратных вызовов один за другим, пока класс не существует (и функция __autoload является одной из них). Если он не существует в конце цепочки, возникает ошибка класса not found.

Когда вы вызываете class_exists без второго параметра (который говорит ему не пытаться загрузить его, если он не существует), он вызывает цепочку обратных вызовов spl_autoload, пока не найдет класс или последний метод называется. Затем он возвращает, если нашел класс.

Так что все зависит от того, что вы делаете в функции автозагрузки. Если вы делаете что-то вроде:

function __autoload($class) {
    $filename = PATH_TO_CLASSES . $class . '.php';
    if (!file_exists($class)) {
        die('Could not find '.$class);
    }
    require_once $filename;
}

Это убьет выполнение и не будет работать как задумано. Вместо этого вы должны сделать:

function __autoload($class) {
    $filename = PATH_TO_CLASSES . $class . '.php';
    if (file_exists($class)) {
        require_once $filename;
    }
}

Это все, что вам нужно сделать.

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

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

11 голосов
/ 11 января 2013

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

class_exists('foo', false)

From PHP Documentation

1 голос
/ 28 сентября 2010

Используйте class_exists внутри функции автозагрузки, затем никогда не используйте ее снова.В этом смысл автозагрузчика.

class App {
    static private $_instance = NULL;

    public function __construct() {
        spl_autoload_register('app::autoLoader');
    }

    public function __destruct() {
    }

    public static function getInstance() {
        if(self::$_instance == NULL) {
            self::$_instance = new App();
        }
        return self::$_instance;
    }

    public static function autoLoader($class) {
        $className = stripslashes($class);
        if (class_exists($className)) {
            return;
        }
        require $className.'.class.php';
    }
}
0 голосов
/ 28 сентября 2010

То, что происходит, вполне логично.Ваша функция __autoload, вероятно, просто включает ClassName.php, поэтому она выполнит оператор echo, который вы там получили.

Если вы пытаетесь решить, есть ли в файле определение класса, вы можете прочитать содержимоефайла (используя file_get_contents или аналогичную функцию), а затем просканируйте это содержимое для определения класса с помощью регулярных выражений или с помощью token_get_all (см. Определение того, какие классы определены вФайл класса PHP ).

...