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
}