Есть ли способ использовать CLASS_EXISTS и __autoload без CRASH скрипта?

Пример:

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") ;
}

person CRISHK Corporation    schedule 28.09.2010    source источник
comment
очевидно необходимо использовать автозагрузку, потому что класс не загружен!   -  person CRISHK Corporation    schedule 28.09.2010
comment
Покажите свою функцию автозагрузки ... Она должна показывать ClassName doesn't exists.... после This will crash all, поскольку по умолчанию ей все равно, если класс не загружен. Я подозреваю, что вы убиваете выполнение в функции __autoload, если не находите класс, и вам не следует ...   -  person ircmaxell    schedule 28.09.2010
comment
Из предоставленного кода результаты не могут быть воспроизведены. Так что опубликуйте еще код.   -  person tplaner    schedule 28.09.2010
comment
Функция __autoload - это любая функция, которая загружает класс и работает правильно. Проблема в том, что он по какой-либо причине находит файлы с кодами выполнения, как в примере   -  person CRISHK Corporation    schedule 28.09.2010
comment
Я пытаюсь узнать, какие строки являются классами, а какие нет в списке FILENAMES.   -  person CRISHK Corporation    schedule 28.09.2010
comment
Нет, покажи свою функцию. По умолчанию PHP ведет себя не так, как вы описываете (как минимум ›= 5.2). Так что причина скорее всего в вашем коде. Так что, если вы покажете свой код, мы сможем помочь. А иначе это всего лишь выстрел в темноте ...   -  person ircmaxell    schedule 28.09.2010


Ответы (4)


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

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

Когда вы вызываете 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;
    }
}

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

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

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

person ircmaxell    schedule 28.09.2010

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

class_exists('foo', false)

Из документации PHP

person Brian Fegter    schedule 11.01.2013
comment
Не уверен, почему это было отклонено, когда это настоящая документация. - person Brian Fegter; 22.10.2013
comment
Потому что вы не обойдете автозагрузчик, установив для второго параметра значение false. Вы просто игнорируете возникающую ошибку, если ПОСЛЕ этого класс все еще не загружался. - person Gregory Magarshak; 10.02.2014
comment
Это вообще не имеет смысла из документации. Почему они назвали это «автозагрузкой» с помощью bool val? - person Brian Fegter; 03.09.2015

Используйте 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';
    }
}
person AutoSponge    schedule 28.09.2010
comment
ХМ? Нет, это не так ... У class_exists множество применений. Один из них - проверить, загружаем ли класс для начала (чтобы узнать, доступен ли он). Кроме того, нет причин вызывать class_exists из функции автозагрузки, поскольку вы знаете, что это еще не сделано (если только кто-то не вызовет его вручную, но они все равно не должны). О, и на вашем месте я бы проверил, существует ли файл на самом деле, прежде чем просто слепить require его. В противном случае вы потеряете возможность проверить, загружается ли класс (что может пригодиться для адаптеров и т. Д.) ... - person ircmaxell; 28.09.2010
comment
В моем примере все файлы классов находятся в одном каталоге. Но да, проверка файлов - хорошая идея. - person AutoSponge; 28.09.2010

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

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

person wimvds    schedule 28.09.2010
comment
Это просто невозможно, в том числе код будет выполнять все, что не содержится в функции или классе. Итак, либо не включайте файл, либо помещайте эхо-операторы внутри функции / класса. - person wimvds; 28.09.2010
comment
Но я не знаю, будет ли файл иметь класс или это просто сценарий, потому что у меня есть список файлов, мне нужно знать, какие из этих имен файлов являются классами или нет. - person CRISHK Corporation; 28.09.2010
comment
Вы должны упомянуть, что в своем исходном вопросе мы не можем читать мысли здесь. Если вы пытаетесь решить, есть ли в файле определение класса, вы можете прочитать содержимое файла (используя file_get_contents или аналогичную функцию), а затем просканировать это содержимое на предмет определения класса с помощью регулярных выражений. - person wimvds; 28.09.2010
comment
Кстати, в зависимости от того, что вы пытаетесь сделать, вы также можете использовать token_get_all (см. stackoverflow.com/questions/928928/) - person wimvds; 28.09.2010
comment
wimvds, это можно в качестве ответа? - person CRISHK Corporation; 29.09.2010