Prowadzę debatę z kolegą na temat prawidłowego użycia (jeśli w ogóle) trigger_error
w kontekście magicznych metod . Po pierwsze, uważam, że trigger_error
należy tego unikać, z wyjątkiem tego jednego przypadku.
Powiedzmy, że mamy klasę z jedną metodą foo()
class A {
public function foo() {
echo 'bar';
}
}
Powiedzmy teraz, że chcemy zapewnić dokładnie ten sam interfejs, ale użyj magicznej metody, aby przechwycić wszystkie wywołania metod
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
Obie klasy są takie same pod względem odpowiedzi, foo()
ale różnią się przy wywoływaniu niepoprawnej metody.
$a->doesntexist(); //Error
$b->doesntexist(); //Does nothing
Moim argumentem jest, że magiczne metody powinny wywoływać, trigger_error
gdy zostanie złapana nieznana metoda
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;
}
}
}
Tak, aby obie klasy zachowywały się (prawie) identycznie
$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28
$b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32
Mój przypadek użycia to implementacja ActiveRecord. Używam __call
do chwytania i obsługi metod, które zasadniczo robią to samo, ale mają modyfikatory takie jak Distinct
lub Ignore
np
selectDistinct()
selectDistinctColumn($column, ..)
selectAll()
selectOne()
select()
lub
insert()
replace()
insertIgnore()
replaceIgnore()
Metody takie jak where()
, from()
, groupBy()
, itd. Są zakodowane.
Mój argument jest podkreślony, gdy przypadkowo dzwonisz insret()
. Gdyby moja aktywna implementacja rekordu zapisała wszystkie metody na stałe, byłby to błąd.
Jak w przypadku każdej dobrej abstrakcji, użytkownik powinien nie znać szczegółów implementacji i polegać wyłącznie na interfejsie. Dlaczego implementacja korzystająca z magicznych metod powinna zachowywać się inaczej? Oba powinny być błędem.
4.something
?