4

Assuming I have this trait:

trait MyTrait{

    protected static $_statVar = 'defaultStaticVal';
    protected $_var = 'defaultVal';

}

And a class that uses it

class MyClass{

    use MyTrait;

}

How would I go about changing the default values, like

use MyTrait{

    MyTrait::$_statVar = 'nonDefaultStaticVal';
    MyTrait->_var = 'nonDefaultVal';

}

I know that the shown syntax is incorrect, and also that currently, it is not allowed to change inherited trait values simply by changin them. What choices/alternatives does that leave me with?

AstroCB
  • 12,337
  • 20
  • 57
  • 73
arik
  • 28,170
  • 36
  • 100
  • 156
  • Any particular reason you can't just change the values in the constructor of your class or with setter methods? – Crisp Mar 07 '13 at 16:43
  • The constructor is within the trait and it's private. I am currently thinking about using the setter method. – arik Mar 07 '13 at 16:53
  • A singleton trait? Maybe take a look here -> http://stackoverflow.com/questions/7104957/building-a-singleton-trait-with-php-5-4 and its use of an `init` method to take care of any extra constructor config – Crisp Mar 07 '13 at 17:03
  • 1
    Nice. But my focus lies more on setting default variable values in traits but changing these defauls for some classes that are using those traits. – arik Mar 07 '13 at 17:10
  • 3
    Then I think you need to rethink supplying the vars inside the traits, use an abstract class instead, which itself uses the trait, but declares the variables outside it. Late static binding can take care of derived classes with different static values – Crisp Mar 07 '13 at 17:18
  • Thanks, that sounds like a good approach. – arik Mar 07 '13 at 17:19

1 Answers1

1

PHP extend class & trait booting control

I created a small helper that solves most situations and expand your execution priorities on the class + trait booting process. The numbers used on the following example respect order of setting. Similar to the Laravel booting mechanism.

A helper class:

class TraitHelper
{
    // The helper will call the boot function on every used trait.
    static public function bootUsedTraits($obj)
    {
        $usedTraits = class_uses($obj);
        foreach ($usedTraits as $traitClass) {
        $path = explode('\\', $traitClass);
        $traitBootMethod = array_pop($path);
        $traitBootMethod = 'boot'.$traitBootMethod;
        if (method_exists($obj, $traitBootMethod)) {
            $obj->$traitBootMethod();
            }
        }
    }
}

Your class:

class MyClass{

    use MyTrait;

    // Class default values
    static protected $a = 1;
    protected $b = 2;

    function __construct()
    {
        // Class setting values before trait
        self::$a = 4;
        $this->b = 5;

        $this->traitVar = 6;


        // Trait setting values
        \TraitHelper::bootUsedTraits($this);


        // Class setting values after trait
        self::$a = 10;
        $this->b = 11;

        $this->traitVar = 12;
    }
}

Your trait:

trait MyTrait {

    // Trait default values
    protected $traitVar = 3;

    // Called on "bootUsedTraits"
    public function bootMyTrait() {
        self::$a = 7;
        $this->b = 8;

        $this->traitVar = 9;
    }
}
Heroselohim
  • 1,241
  • 1
  • 18
  • 23