У меня спор с коллегой по поводу правильного использования (если есть) trigger_error
в контексте магических методов . Во-первых, я думаю, что этого trigger_error
следует избегать, за исключением одного этого случая.
Скажем, у нас есть класс с одним методом foo()
class A {
public function foo() {
echo 'bar';
}
}
Теперь скажем, что мы хотим предоставить точно такой же интерфейс, но используем магический метод для перехвата всех вызовов метода
class B {
public function __call($method, $args) {
switch (strtolower($method)) {
case 'foo':
echo 'bar';
break;
}
}
}
$a = new A;
$b = new B;
$a->foo(); //bar
$b->foo(); //bar
Оба класса одинаковы в том, как они отвечают, foo()
но различаются при вызове недопустимого метода.
$a->doesntexist(); //Error
$b->doesntexist(); //Does nothing
Мой аргумент заключается в том, что магические методы должны вызывать trigger_error
при обнаружении неизвестного метода
class B {
public function __call($method, $args) {
switch (strtolower($method)) {
case 'foo':
echo 'bar';
break;
default:
$class = get_class($this);
$trace = debug_backtrace();
$file = $trace[0]['file'];
$line = $trace[0]['line'];
trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
break;
}
}
}
Так что оба класса ведут себя (почти) одинаково
$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28
$b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32
Мой вариант использования - реализация ActiveRecord. Я использую, __call
чтобы поймать и обработать методы, которые по сути делают то же самое, но имеют модификаторы, такие как Distinct
или Ignore
, например,
selectDistinct()
selectDistinctColumn($column, ..)
selectAll()
selectOne()
select()
или
insert()
replace()
insertIgnore()
replaceIgnore()
Такие методы , как where()
, from()
, groupBy()
и т.д. жестко закодированы.
Мой аргумент высвечивается, когда вы случайно звоните insret()
. Если моя реализация активной записи жестко закодирует все методы, это будет ошибкой.
Как и в случае любой хорошей абстракции, пользователь должен не знать о деталях реализации и полагаться исключительно на интерфейс. Почему реализация, использующая магические методы, должна вести себя иначе? Оба должны быть ошибкой.
источник
4.something
?__call()
для динамической маршрутизации, действительно ли это так неразумно ожидать, что где-то на пути, кто-то может захотеть обработать случай, когда это не удается? Во всяком случае, это происходит по кругу, так что это будет мой последний комментарий. Делайте что хотите, в конце дня это сводится к суждению: Лучшая поддержка против последовательности. Оба метода приведут к одинаковому воздействию на приложение в случае отсутствия специальной обработки.Я собираюсь высказать свое убежденное мнение, но если вы используете
trigger_error
где-то, то вы делаете что-то не так. Исключения - это путь.Преимущества исключений:
Решение ваших проблем, вызов метода, который не существует, может быть допустимой возможностью . Это полностью зависит от контекста кода, который вы пишете, но в некоторых случаях это может произойти. С учетом вашего конкретного случая использования некоторые серверы баз данных могут предоставлять некоторые функции, которые другие не могут. Использование
try
/catch
и исключений в__call()
сравнении с функцией для проверки возможностей - это совершенно другой аргумент.Единственный вариант использования, который я могу придумать для использования,
trigger_error
- дляE_USER_WARNING
или ниже. Запуск,E_USER_ERROR
хотя это всегда ошибка на мой взгляд.источник
trigger_error
в контексте __call или __callStatic имитирует поведение языка по умолчаниюNoMethodError
который вы можете поймать, если захотите. По моему личному мнению, ошибки - это огромная ошибка в PHP. То, что ядро использует неработающий метод для сообщения об ошибках, не означает, что ваш собственный код должен это делать.Стандартные ошибки PHP следует считать устаревшими. PHP предоставляет встроенный класс ErrorException для преобразования ошибок, предупреждений и уведомлений в исключения с полной правильной трассировкой стека. Вы используете это так:
Используя это, этот вопрос становится спорным. Встроенные ошибки теперь вызывают исключения, так что ваш собственный код также должен.
источник
E_NOTICE
s в исключения. Это было бы плохо.ИМО, это вполне допустимый вариант использования для
trigger_error
:Используя эту стратегию, вы получаете
$errcontext
параметр, если делаете это$exception->getTrace()
внутри функцииhandleException
. Это очень полезно для определенных целей отладки.К сожалению, это работает, только если вы используете
trigger_error
напрямую из своего контекста, что означает, что вы не можете использовать функцию / метод-обертку для псевдонимаtrigger_error
функции (поэтому вы не можете сделать что-то подобное,function debug($code, $message) { return trigger_error($message, $code); }
если хотите, чтобы данные контекста были в вашей трассировке).Я искал лучшую альтернативу, но пока не нашел.
источник