如何启动trait定义的构造函数和析构函数以及类的构造函数和析构函数。例如,
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();
我应该得到几行文本但是我没有得到,因为C类的构造函数被明确地调用了。有没有办法实现这个目标?
答案 0 :(得分:5)
构造类时,C的构造函数和析构函数优先于trait构造函数和析构函数:
来自基类的继承成员被Trait插入的成员覆盖。 优先顺序是当前类的成员覆盖Trait方法,这些方法将覆盖继承的方法。
换句话说,从C中删除空构造函数和析构函数,将使用trait的构造函数和析构函数。没有办法使用C和traits,构造函数和析构函数来完成这项工作,因为traits不像常规继承那样工作。
一般情况下,我会建议不要让Traits拥有自己的构造函数或析构函数,因为你无法实例化Traits。您从具有特征的类实例化,该类应该处于控制之中。考虑在特征中添加onCreate()
或onDestroy()
方法,并在C上使用相应的魔术方法调用它们。您可以通过在C中对特征__construct进行别名来实现相同的效果,但我认为这样可以解决这个问题。
答案 1 :(得分:3)
添加Aeremdir的答案:来自基类和多个特征的继承构造函数......
<?php
trait T1 {
public function __construct() {
$this->someval |= 0b0001;
echo "T1::__construct() done\n";
}
}
trait T2 {
public function __construct() {
$this->someval |= 0b0010;
echo "T2::__construct() done\n";
}
}
class C1 {
protected $someval;
public function __construct() {
$this->someval = 0b10000000;
echo "C1::__construct() done\n";
}
}
class C2 extends C1 {
use T1, T2 {
T1::__construct as private T1__construct;
T2::__construct as private T2__construct;
}
public function __construct() {
parent::__construct();
$this->T1__construct();
$this->T2__construct();
$this->someval |= 0b00100000;
echo "C2::__construct() done\n";
}
public function someval() {
$str = base_convert($this->someval, 10, 2);
$len = strlen($str);
if($len < 8)
$str = str_repeat('0', 8 - $len) . $str;
return '0b' . $str;
}
}
$v1 = new C2();
echo $v1->someval();
?>
在PHP 7.0.5下,此代码导致...
C1 :: __ construct()完成
T1 :: __ construct()完成
T2 :: __ construct()完成了 C2 :: __ construct()完成了
0b10100011
答案 2 :(得分:2)
您必须为Trait
的方法定义自定义名称。然后你可以从你的班级调用这些方法。
由于该类的方法会覆盖Trait
的方法,您必须为Trait
的方法分配不同的名称:
class C
{
use Audit {
Audit::__construct as auditConstruct;
Audit::__destruct as auditDestruct;
}
public function __construct()
{
$this->auditConstruct();
}
public function __destruct()
{
$this->auditDestruct();
}
}