Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 未调用trait定义的构造函数/析构函数_Php_Traits - Fatal编程技术网

Php 未调用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定义的构造函数和析构函数以及类的构造函数和析构函数。比如说,

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。