PHP __call vs method_exists

Проект, над которым я работаю, содержит что-то вроде обертки для call_user_func (_array), которая выполняет некоторые проверки перед выполнением. Одной из таких проверок является метод_exists (в том случае, когда поставленный первый аргумент является экземпляром класса, а второй - именем метода) Другой is_callable. Функция будет генерировать исключение, если одна из этих проверок терпит неудачу.

Мой код содержит массив с именами функций (setFoo, setBar и т.д.) и функцию php magic для перегрузки (__call), которая обрабатывает установку, замену и удаление определенных переменных (лучше некоторые элементы массива).

Проблема: method_exists вернет false, если функция не определена.

Есть ли у меня шанс получить true, если функция __call выполняет правильную обработку запроса?

Ответы

Ответ 1

__call обрабатывает вызовы методов, которые не существуют. method_exists - это метод интроспекции, который проверяет существование метода.

Как можно определить __call для обработки метода? Я думаю, что вы должны выбросить исключение вручную в __call, если не обрабатываете свой запрос и не поймаете исключение в коде, который иначе использовал бы method_exists. BadMethodCallException существует для этой цели.

Ответ 2

Посмотрите is_callable().

Но нет, если метод __call() обрабатывает только некоторые имена, тогда вам понадобится другой способ проверить, будет ли вызов успешным.

Могу ли я предложить интерфейс с методом canCall($function) или что-то еще? Затем проверьте, реализует ли класс интерфейс. Если это не так, просто используйте is_callable().

Ответ 3

method_exists пробует две вещи:

  • Ищет имя метода в таблице функций класса. Это методы типа function foo() {}.
  • Проверяет, имеет ли класс (код C) функцию (C код) get_method(), и если она вызывает ее, чтобы позволить реализации класса решить.

Вам понадобится последний. Но этот get_method() не "расширен" для кода PHP скрипт, т.е. Не существует способа, чтобы get_method() вызывал некоторый определенный пользователем код PHP скрипт (и что бы этот PHP-код возвращал?).

Итак, ответ на мои лучшие знания: Нет, это невозможно (еще?).

Реализация ZEND_FUNCTION(method_exists) может быть найдена в zend/zend_builtin_functions.c и, я думаю, достаточно читабельна, даже если вы не знаете C но PHP.

Ответ 4

У меня возникло бы желание использовать method_exists в вашей функции __call и throw a Exception, если это произойдет, и оберните все в блок try catch вместо использования is_callable функция.

Ответ 5

Если вы действительно уверены, что _call всегда имеет спад, вы можете сделать:

if (method_exists($this, $method_name) || method_exists($this, '__call')) {
  // Call of the method
}