2

I have a static function being called that is giving a strange error. Here is an example of the php code:

class foo {
     public $stat;
     public function __construct() {
         $this->stat = stat::isValid('two');
     }
}

class stat {
     protected static $invalidNumbers = array('one', 'two');
     function isValid($number) {
         return in_array($number, static::$invalidNumbers);
     }
}

$foo = new foo();
var_dump($foo->stat);

This code results in the following error:

Fatal error: Access to undeclared static property: foo::$invalidNumbers

However changing static:: to self:: makes the code behave as expected. I was under the impression that in this context using static:: should work.

Why does this error occur using static?

Schleis
  • 41,516
  • 7
  • 68
  • 87

3 Answers3

6

You begin by making a method call in a static context:

stat::isValid('two');

When you do this, PHP "remembers" the context from within which isValid was called specifically so that it can resolve what to bind to when it sees something like static:: inside the method body, determine if some property you are trying to access is visible, and in general be able to implement some OO-related language features.

The actual method isValid is not static, but PHP still allows you to call it using the static method syntax (it does give an E_STRICT warning about that). However, this has the side effect that isValid itself does not participate in modifying the curent calling context for (late) static bindings.

The result: when PHP sees static::$invalidNumbers, it still thinks you are halfway through making a static method call from within the foo class! Once you realize this, it is obvious why static:: resolves to foo:: and it ends up looking for the property at the wrong place.

If you correctly declare isValid as static

 static function isValid($number) {
     return in_array($number, static::$invalidNumbers);
 }

then upon calling the method PHP does update its context internally and manages to bind to the intended member.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • Good answer! It is indeed so, that the code in question is working when you have declared `foo::invalidNumbers`. Although this makes totally sense, I didn't realized this before. – hek2mgl Apr 25 '13 at 20:45
3

You are trying to call the method stat::isValid() statically but have not declared it static. Change the stat class to:

class stat {
     protected static $invalidNumbers = array('one', 'two');

     // needs to be declared static
     static function isValid($number) {
         return in_array($number, static::$invalidNumbers);
     }
}

Note that, if you add

| E_STRICT

to your error_reporting in php.ini you would see a message like:

Strict standards: Non-static method stat::isValid() should not be called statically, assuming $this from incompatible context in ...

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
2

Declare static method properly

Replace

 function isValid($number) {

With

public static function isValid($number) {   
         ^--- here  
Baba
  • 94,024
  • 28
  • 166
  • 217