I'm having a debate with a colleague over the correct usage (if any) of trigger_error in the context of magic methods. Firstly, I think that trigger_error should be avoided except for this one case.

Say we have a class with one method foo()

class A { public function foo() { echo 'bar'; } }

Now say we want to provide the exact same interface but use a magic method to catch all method calls

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

Both classes are the same in the way they respond to foo() but differ when calling an invalid method.

$a->doesntexist(); //Error $b->doesntexist(); //Does nothing

My argument is that magic methods should call trigger_error when a unknown method is caught

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; } } }

So that both classes behave (almost) identically

$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28 $b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32

My use-case is an ActiveRecord implementation. I use __call to catch and handle methods that essentially do the same thing but have modifiers such as Distinct or Ignore , e.g.

selectDistinct() selectDistinctColumn($column, ..) selectAll() selectOne() select()

or

insert() replace() insertIgnore() replaceIgnore()

Methods like where() , from() , groupBy() , etc. are hard-coded.

My argument is highlighted when you accidentally call insret() . If my active record implementation hardcoded all of the methods then it would be an error.

As with any good abstraction, the user should be unaware of the implementation details and rely solely on the interface. Why should the implementation that uses magic methods behave any differently? Both should be an error.