6

I've found some strange (for me) behavior of the PHP interpreter and I'm not sure if it's safe to use it in production or not.

When we call Foo::bar() and the Foo class does not have the static bar method but it has non-static bar method, the interpreter will invoke non-static bar on null (yes, it sounds ridiculous). I expected the __callStatic to be invoked in this case. But it's not what is happening for some reason.

I've then found a handy usage for this behavior: to provide the class with static and non-static methods with the same name like this:

class Foo
{
    public function bar(){
        if (isset($this)) {
            $this->nonStaticBar();
        } else {
            static::staticBar();
        }
    }

    private function nonStaticBar() {
        echo "Non-static\n";
    }

    private static function staticBar() {
        echo "Static\n";
    }
}

(new Foo())->bar(); // Output: "Non-static"
Foo::bar(); // Output: "Static"

Yes I know, that this approach is not elegant and architecturally wrong. The question is if it's safe (standard-compliant) to use this "feature" or not. Are there any other cases when isset($this) can equal false?

Community
  • 1
  • 1
Kolyunya
  • 5,973
  • 7
  • 46
  • 81

1 Answers1

3

While your above example does work, it is not best practice. This is recognized in the PHP documentation here and states that in PHP versions before version 7, if E_STRICT error reporting is enabled then it will emit the error:

Strict Standards: Non-static method Foo::bar() should not be called statically in /Path/to/file.php on line 22

Additionally in PHP versions 7 and above calling static functions statically is deprecated and will cause the following error upon execution:

Deprecated:  Non-static method Foo::bar() should not be called statically in /Path/to/file.php on line 22
C.Liddell
  • 1,084
  • 10
  • 19
  • Thank's for the reference to the docs. I believe that the `__callStatic` must be called in this case. The class does not have the static method with such name. And the docs state that `__callStatic() is triggered when invoking inaccessible methods in a static context.` – Kolyunya Apr 03 '16 at 21:58
  • @Kolyunya An interesting thing that I noticed when trying to assign/reassign the variable `$this` within a static (or non-static) method is that it will return the fatal error `Fatal error: Cannot re-assign $this in /Path/to/file.php`. So, even though it's not best practice, I cannot imagine another case where `isset($this)` would equal `false`. – C.Liddell Apr 04 '16 at 01:35