3
<?php

class T {
        public function x(){
                return true;
        }    
}
var_dump(T::x());

class X {
        public function x(){
                return true;
        }

}    
var_dump(X::x());

This code results in:

bool(true)
PHP Fatal error:  Non-static method X::x() cannot be called statically in test.php on line 16

Why does T::x() works (when it should fail) and X::x() fails (as it should)?

8
  • 1
    well, self, parent and static are also doing non-static calls. Are you sure that $x = T::x(); is successful?! Commented Oct 10, 2013 at 17:47
  • Notice that in testY(), you are making a T object but not an X object. That seems to be making a difference. Commented Oct 10, 2013 at 17:57
  • @bwoebi that's exactly what i find strange in all this. I copy pasted the core i'm running. feel free to reproduce and see if it works any different. also, will update with my php/phpunit versions, that may be useful. Commented Oct 10, 2013 at 18:15
  • 1
    @gcb please modify your question a bit as it actually is totally unrelated to phpunit… (and it should be searchable by google with more obvious search queries…) 3v4l.org/l5v8p is much more comprehensive as a question… Commented Oct 10, 2013 at 18:30
  • @bwoebi done. question is much clearer now. thanks. Commented Oct 10, 2013 at 19:12

1 Answer 1

3

X::x() is actually a PHP4 style constructor, as it share the same name of the class. And calling constructors of a class in a static way raises a fatal error:

Non-static method X::x() cannot be called statically, assuming $this from incompatible context

This actually is the case for all non-static magic methods as you can see in the implementation: http://lxr.php.net/xref/PHP_5_5/Zend/zend_compile.c#1636

The only case where it might be implicitely called statically (and raise an E_STRICT) is when the function has no special handling:

if (some large if/else's for the magic methods) {
    // flag isn't set…
} else {
    CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
}
Sign up to request clarification or add additional context in comments.

5 Comments

@gcb because T::x() isn't a PHP4 style constructor (and this way not a magic method what allows static calls from incompatible context)? For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, and the class did not inherit one from a parent class, it will search for the old-style constructor function, by the name of the class. from php.net/manual/en/language.oop5.decon.php
i still can't see how T::x() is any different than X::x(). If i remove the first test, which creates new T() from the code, the same thing happens. T::x() does not throw error. but X::() does.
@gcb X::x() is a constructor because the method name (x) is equal to the class name (X) (when ignoring case). T::x() is not a constructor because the method name (x) isn't equal to the class name (T). And as said in my answer: static calls on constructors fatal.
ah! of course! sorry, for some reason wasn't seeing that even with the previous explanations!
keep in mind that apparently is not case sensitive when calling classes, so x and X are the same

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.