Kvothe
Kvothe

Reputation: 1837

How to access class members in traits (or get a similar behaviour)?

This is a follow-up to my previous question about resolving the diamond issue in php.

As I state in that question, I resolve my problem by using traits and passing the instance of the class to the method of the trait. Such as:

trait SecurityTrait
{
    public function beforeExecuteRouteTrait($controller, Dispatcher $dispatcher)
    {
        // Do something that makes use of methods/members of the controller
    }
}

class AppController extends Controller
{
    use SecurityTrait;

    public function beforeExecuteRoute(Dispatcher $dispatcher)
    {
        return $this->beforeExecuteRouteTrait($this, $dispatcher);
    }
}

However, I am still uncomfortable with this as I don't think this is how traits are really supposed to be used. In my reading I haven't found any way in which to access class members in traits (make $this inside a trait refer to the class using it). Is this possible? Or is there another way to implement a similar behaviour?

After reading some of the answers...

Previously I thought I had received errors when using $this->... inside the trait and this led me to believe the trait could not access anything to do with the underlying class. After reading the answers I tried altering my code to use $this->... inside a trait again and it works - which means a typo several weeks ago has given me far too much headache...

The example given previously now looks like this

trait SecurityTrait
{
    public function beforeExecuteRoute(Dispatcher $dispatcher)
    {
        // Do something that makes use of methods/members of the controller
    }
}

class AppController extends Controller
{
    use SecurityTrait;
}

Much cleaner and more easily understandable but provides the same functionality.

Upvotes: 7

Views: 10069

Answers (2)

Andris
Andris

Reputation: 6113

If you use a trait inside a class then that trait has full access to all class's members and vice versa - you can call private trait methods from the class itself.

Think of traits as code that literally gets copy/pasted into the class body.

For example:

trait Helper
{
    public function getName()
    {
        return $this->name;
    }

    private function getClassName()
    {
        return get_class($this);
    }
}

class Example
{
    use Helper;

    private $name = 'example';

    public function callPrivateMethod()
    {
        // call a private method on a trait
        return $this->getClassName();
    }
}

$e = new Example();
print $e->getName(); // results in "example"
print $e->callPrivateMethod(); // results in "Example"

In my view referencing classes in traits is not the best way to use them but there's nothing stopping anyone from doing it.

Upvotes: 16

Machavity
Machavity

Reputation: 31614

No, that's exactly what Traits are for. Your class already extends a class so you can't inherit the methods and variables of any other classes.

Think of a Trait like copy/paste for code execution. When a class includes a Trait, it's just as if you had written all that code into the class itself.

Upvotes: 3

Related Questions