Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor/destructor defined by trait is not being called

Tags:

php

traits

How can I launch constructor and destructor defined by trait along with the class' constructor and destructor as well. For example,

trait Audit
{
    public function __construct()
    {
        parent::__construct(); // Doesn't work...

        $this->_name = __CLASS__;

        $this->AuditAction('Started');
    }

    public function __destruct()
    {
        parent::__destruct(); // Doesn't work...

        $this->AuditAction('Ended');

        echo $this->_log;        
    }

    public function AuditAction($n)
    {
        $this->_log .= $this->GetCurrentTimeStamp() . ' ' . $this->_name . ": $n" . PHP_EOL;
    }

    private function GetCurrentTimeStamp()
    {
        return (new DateTime())->format('[Y-m-d H:i:s]');
    }

    private $_name, $_log = '';
}

class C
{
    use Audit;

    public function __construct()
    {

    }

    public function __destruct()
    {

    }
}

$c = new C();

I should get couple of lines of text but I get none since class C's constructor is explicitly called instead. Is there a way to achieve this?

like image 235
nhaa123 Avatar asked Jan 04 '13 12:01

nhaa123


1 Answers

The constructor and destructor of C will have precedence over the trait constructor and destructor when the class is composed:

An inherited member from a base class is overridden by a member inserted by a Trait. The precedence order is that members from the current class override Trait methods, which in return override inherited methods.

Source: http://php.net/traits

In other words, remove the empty constructor and destructor from C and the trait's constructor and destructor will be used. There is no way to make this work with both, C and the traits, constructor and destructor, because traits do not work like regular inheritance.

In general, I would advise against giving Traits their own constructors or destructors because you cannot instantiate Traits. You instantiate from a class having a Trait and that class should be in control. Consider adding an onCreate() or onDestroy() method to the trait instead and call these from the appropriate magic methods on C. You could achieve the same by aliasing the traits __construct in C, but I think this waters down semantics.

like image 180
Gordon Avatar answered Oct 26 '22 22:10

Gordon