Когда именно вызывается загрузчик?


У меня есть загрузчик, который зарегистрирован с помощью spl_autoload_register():

class MyAutoLoader{
   public function __construct(){
       spl_autoload_register(array($this, 'loader'));
   }

   public function loader($className){
       var_dump($className);
   }
}

$al = new MyAutoLoader(); //Register the autoloader

Из var_dump(), похоже, что автозагрузчик вызывается для множества вещей, таких как данные, которые должны быть вставлены в базу данных, параметризованные запросы SQL, а что нет:

string 'name' (length=4)

string 'a:2:{s:5:"label";s:4:"Name";s:8:"required";b:1;}' (length=48)

string 'en_US' (length=5)

string 'object' (length=6)

string 'name = ?' (length=8)

Эти вещи никогда не будут классами, поэтому их никогда не следует загружать с помощью new или class_exists() и т.д.

При каких обстоятельствах/вызовах функций вызываются автозагрузчики? Я хотел бы прекратить автоматическую загрузку "Имена классов", которые не являются классами от вызова, потому что каждый $className проверяется с помощью file_exist(), и проверка этих строк данных довольно неэффективна.


Проблема решена. Сначала я сделал обратную трассировку, как предложил Брэд, и сбросил трассировки в файл (просто добавьте небольшой фрагмент, который открывает файл и добавляет к нему).

Очевидно, что след был очень большим, но я выбрал самый простой, который смог найти. Кстати, этот след оказался тем, который вызвал оболочка базы данных (ORM), которую я написал, чтобы обернуть вокруг потрясающей библиотеки RedBean ORM. Результаты моего сброса $className также подтверждают это, поскольку эти строки являются данными, входящими в базу данных или выходящими из нее.

Сказав это, у меня есть __call(), который перехватывает методы в моей оболочке базы данных, выполняет некоторую обработку, передает ее в RedBean, обрабатывает результат и затем отправляет его обратно вызывающему.

Проблема: Во время обработки я совершаю звонки по is_subclass_of() и экземпляр , который, очевидно, попросит загрузчик попытаться загрузить класс (поскольку у нас нет ни одного загруженного класса с именем name =?, и он не существует).

Решение состояло в том, чтобы на самом деле убедиться, что у нас есть object, прежде чем звонить is_subclass_of() и instanceof: if(is_object($someproperty) && is_subclass_of($someproperty)).

Если $someproperty не является объектом, if немедленно замыкается и instanceof и is_subclass_of() никогда не вызывается, что означает, что вызов загрузчика никогда не выполняется сделано.

Как упоминал Брэд, включение всевозможных вещей в автозагрузчик с помощью require_once может представлять собой огромный риск для безопасности, и в то же время так часто попадать в файловую систему с помощью file_exists() тоже довольно неэффективно.

Итак, в заключение, загрузчик вызывается каждый раз, когда вы используете instanceof, is_subclass_of, другие функции типа класса, функции существования классов и методы отражения, как указал Чарльз в своем ответе.

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

Author: F21, 2012-12-20

2 answers

При каких обстоятельствах/вызовах функций вызываются автозагрузчики?

Я понимаю, что в конечном итоге это в основном второстепенный вопрос, учитывая проблемы, отмеченные в комментариях, но на него все равно стоит ответить.

Функции автоматической загрузки, которые являются __autoload() функция в вашем коде или обратные вызовы, зарегистрированные через spl_autoload_register, вызываются, когда - и только когда - PHP необходимо получить доступ к классу, который не был определен. Это сделано везде за редкими исключениями, такими как class_exists, у которых есть аргументы, которые говорят PHP не вызывать никаких загрузчиков.

В руководстве по PHP есть страница, посвященная автоматической загрузке . Я рекомендую просмотреть его, если возникнет какая-либо путаница.

 2
Author: Charles, 2012-12-20 05:07:18

Вы можете использовать debug_backtrace или debug_print_backtrace, чтобы узнать, где именно вызывается функция автозапуска.

Технически он должен вызываться PHP только тогда, когда скрипт ссылается на имя класса, которого не существует.

 0
Author: Petah, 2012-12-20 04:16:58