9

クラスのコンストラクタとデストラクタとともに、特性によって定義されたコンストラクタとデストラクタを起動するにはどうすればよいですか。例えば、

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 のコンストラクターが明示的に呼び出されるため、何も取得できません。これを達成する方法はありますか?

4

3 に答える 3

6

C のコンストラクタとデストラクタは、クラスが合成されるときに、特性のコンストラクタとデストラクタよりも優先されます。

基本クラスから継承されたメンバーは、特性によって挿入されたメンバーによってオーバーライドされます。優先順位は、現在のクラスのメンバーが Trait メソッドをオーバーライドし、その代わりに継承されたメソッドをオーバーライドするというものです。

ソース: http://php.net/traits

つまり、C から空のコンストラクタとデストラクタを削除すると、トレイトのコンストラクタとデストラクタが使用されます。トレイトは通常の継承のように機能しないため、C とトレイト、コンストラクター、デストラクタの両方でこれを機能させる方法はありません。

一般に、Traits をインスタンス化できないため、Traits に独自のコンストラクタまたはデストラクタを与えることはお勧めしません。Trait を持つクラスからインスタンス化すると、そのクラスが制御されます。onCreate()代わりにトレイトにorメソッドを追加し、onDestroy()C の適切なマジック メソッドからこれらを呼び出すことを検討してください。C でトレイト __construct をエイリアス化することで同じことを実現できますが、これはセマンティクスを骨抜きにしていると思います。

于 2013-01-04T12:38:35.957 に答える
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

于 2016-12-18T17:17:11.893 に答える
3

のメソッドのカスタム名を定義する必要があります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();
    }
}
于 2016-12-02T19:21:08.600 に答える