Reputation: 30881
How can one detect that a static function called non-statically?
For example, in this case:
class Foo
{
public static function bar()
{
// How can I tell here that bar() is called on an instance?
//var_dump(debug_backtrace()[0]['type'] == '::');
// at all times the above prints bool(true)
return 1;
}
}
// later in the code
$foo = new Foo();
$foo::bar(); // that's fine
// even later
$foo->bar(); // this should not happen, yet it's here and there
I want to debug and eradicate cases such as on the last line above: someone somewhere wrongly calls a function on an instance, expecting that it would return something related to the instance in subject; instead one gets a somewhat related constant. Subsequently I need to know when this happens. If hell breaks loose or an exception gets thrown is fine with me too.
So far I've found that non-static calls for static functions are internally translated into static calls, hence debug_backtrace()[0]['type']
tells us nothing (it's ::
in both cases).
Upvotes: 2
Views: 379
Reputation: 30881
If you don't want to turn off E_STRICT
for eternity, there's a way.
If the class Foo
is, by sheer luck or providence, instantiated only in a couple of places like so:
public function getFoo()
{
return new Foo();
}
Then if we subclass it and redefine bar()
:
class Foo2 extends Foo
{
public static function bar()
{
throw new Exception("You're calling Foo::bar() on an instance");
}
}
Then if we replace Foo
with Foo2
where it were instantiated...
public function getFoo()
{
//return new Foo();
return new Foo2();
}
Exception will be thrown upon calling the above new static method:
$q = Foo::bar(); // no error just as before
$foo = $other->getFoo();
$foo->bar(); // throws exception
If anyone ever calls $foo->bar();
on this kind-of-Foo
, he would be quickly notified that he's making a mistake.
Upvotes: 0
Reputation: 14233
The solution is twofold:
First one needs to disable E_STRICT
reporting:
error_reporting(error_reporting() ^ E_STRICT);
Next one should remove static
keyword from the function's declaration.
public /* static */ function bar()
Now it is possible to see if a function being called statically or dynamically with help of debug_backtrace function:
class Foo
{
public function bar()
{
$calledStatically = debug_backtrace()[0]['type'] == '::';
if (!$calledStatically) {
throw new Exception("Should not happen");
}
// ...
}
}
From the documentation:
type
(string): The current call type. If a method call, "->" is returned. If a static method call, "::" is returned. If a function call, nothing is returned.
Quick demo.
Foo::bar(); // normal result returned
$foo = new Foo();
$foo->bar(); // throws exception
Upvotes: 2