1

I was wondering what the static keyword returns in a trait? It seems like it's being bound to the trait and not the class that uses it. For example:

trait Example
{
    public static $returned;

    public static function method()
    {
        if (!eval('\\'.get_called_class().'::$returned;')) {
            static::$returned = static::doSomething();
        }   

        return static::$returned;
    }

    public static function doSomething()
    {
        return array_merge(static::$rules, ['did', 'something']);
    }
}

class Test {}

class Test1 extends Test
{
    use Example;

    protected static $rules = ['test1', 'rules'];
}

class Test2 extends Test
{
    use Example;

    protected static $rules = ['test2', 'rules'];
}

// usage

Test1::method();
// returns expected results:
// ['test1', 'rules', 'did', 'something'];

Test2::method();
// returns unexpected results:
// ['test1', 'rules', 'did', 'something'];
// should be:
// ['test2', 'rules', 'did', 'something'];

I could get it work with some nasty eval() in the method() method:

public static function method()
{
    if (!eval('\\'.get_called_class().'::$returned;')) {
        static::$returned = static::doSomething();
    }   

    return static::$returned;
}

Now it simply matches it against \My\Namespaced\Class::$returned but it is also weird as as checking a static property, $returned, which was defined in the trait to begin with and was bound correctly to the class that uses it. Then why won't the static::$returned work?

The PHP version is 5.6.10.

Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
kfirba
  • 5,231
  • 14
  • 41
  • 70
  • 2
    There's an example in [the documentation](http://php.net/manual/en/language.oop5.traits.php) that confirms your findings. What more do you wish to know? – Lightness Races in Orbit Jul 25 '15 at 18:49
  • @LightnessRacesinOrbit Where? I've read through this and can't find it – kfirba Jul 25 '15 at 18:50
  • Press Ctrl+F and type in "static".... – Lightness Races in Orbit Jul 25 '15 at 18:50
  • you are missing `function` keywords in function definition. – pinkal vansia Jul 25 '15 at 18:52
  • @pinkalvansia that was a mistake, the real code has the `function` keyword. Thanks for pointing this. – kfirba Jul 25 '15 at 18:53
  • @LightnessRacesinOrbit There is no reference that say that the `static` keyword is bound to the trait and not the class that uses the trait. – kfirba Jul 25 '15 at 18:54
  • @kfirba I am getting expected output!! – pinkal vansia Jul 25 '15 at 18:57
  • @pinkalvansia how is that possible? that's super weird.. Is there way to `var_dump` what the static keyword is? – kfirba Jul 25 '15 at 19:00
  • Look at the example. – Lightness Races in Orbit Jul 25 '15 at 19:04
  • @LightnessRacesinOrbit Well yea, the example says the exact opposite of my findings. The example is what I expect to happen but something else happens. What could possibly interfere? Maybe if the class that uses the trait is extending another class is may cause a bug? – kfirba Jul 25 '15 at 19:06
  • I guess the difference is between function-`static` and member-`static`. – Lightness Races in Orbit Jul 25 '15 at 19:10
  • @LightnessRacesinOrbit, I think you're on to something. There's an explanation of trait 'contexts' here that may help: https://stackoverflow.com/a/56935557/2137316. I suspect when you call a static method defined in the trait, you're talking to the trait, not the class using it. Meaning what you get back is the initialization value. I'd bet if you overrode the "method()" in Test2, you'd get the value you're expecting. I'd also bet if you gave that property a default value, Test1::method() would seem to ignore the reassignment just as Test2 is. Only a guess though, I haven't tested the theory. – kmuenkel Dec 20 '22 at 15:35

1 Answers1

0

so why u use late static binding here?

try this

trait Example
{
    public static $returned;

    public static function method()
    {
        if (!self::$returned) {
            self::$returned = self::doSomething();
        }   

        return self::$returned;
    }

    public static function doSomething()
    {
        return array_merge(self::$rules, ['did', 'something']);
    }
}
M0rtiis
  • 3,676
  • 1
  • 15
  • 22