Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 245
Kvothe Avatar asked Dec 08 '22 01:12

Kvothe


2 Answers

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.

like image 170
Andris Avatar answered Feb 28 '23 01:02

Andris


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.

like image 35
Machavity Avatar answered Feb 28 '23 00:02

Machavity