Php 未调用trait定义的构造函数/析构函数
如何启动trait定义的构造函数和析构函数以及类的构造函数和析构函数。比如说,Php 未调用trait定义的构造函数/析构函数,php,traits,Php,Traits,如何启动trait定义的构造函数和析构函数以及类的构造函数和析构函数。比如说, trait Audit { public function __construct() { parent::__construct(); // Doesn't work... $this->_name = __CLASS__; $this->AuditAction('Started'); } public function __de
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的构造函数被显式调用了。有没有办法做到这一点?当类组成时,C的构造函数和析构函数将优先于trait构造函数和析构函数: 从基类继承的成员由Trait插入的成员覆盖优先顺序是来自当前类的成员重写Trait方法,Trait方法反过来重写继承的方法 资料来源: 换句话说,从C中删除空构造函数和析构函数,将使用trait的构造函数和析构函数。无法同时使用C和traits、构造函数和析构函数,因为traits不像常规继承那样工作
一般来说,我建议不要给Traits赋予它们自己的构造函数或析构函数,因为不能实例化Traits。您从一个具有特征的类实例化,并且该类应该处于控制之中。考虑将<代码> OnCeCuto()/代码>或<代码> OnDebug()/代码>方法替换为特性,并从C.上的适当的魔术方法调用这些方法。您可以通过在C中混淆特征结构来达到相同的效果,但我认为这会降低语义。
您必须为代码<特性> <代码>的方法定义自定义名称。然后可以从类中调用这些方法
由于类的方法覆盖了Trait
的方法,因此必须为Trait
的方法指定不同的名称:
class C
{
use Audit {
Audit::__construct as auditConstruct;
Audit::__destruct as auditDestruct;
}
public function __construct()
{
$this->auditConstruct();
}
public function __destruct()
{
$this->auditDestruct();
}
}
添加到的答案:从基类和多个特性继承的构造函数
<?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();
?>
在PHP7.0.5下,此代码导致
C1::_构造()完成T1::_构造()完成
T2::_构造()完成
C2::_构造()完成
0b10100011
这是不对的。可以调用Trait的方法,这些方法被使用Trait的类覆盖。使用其他内容更改Trait中方法的名称就足够了。@Aerendir如果我对C源代码的读取正确,则带别名的ctor或dtor将不再包含ctor或dtor函数标志。这意味着这在技术上是不可能的,因为它们当时只是常规方法。然而,您显然是对的,您可以通过别名将它们作为常规方法执行,这将有效地解决OP的问题。但这更像是调用自定义的
onCreate()
或onDestroy()
方法,而不是调用实际的CTOR或DTOR。