9 votes

Le constructeur/destructeur défini par un trait n'est pas appelé

Comment puis-je lancer le constructeur et le destructeur définis par le trait en même temps que le constructeur et le destructeur de la classe ? Par exemple,

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();

Je devrais obtenir quelques lignes de texte mais je n'en obtiens aucune puisque le constructeur de la classe C est explicitement appelé à la place. Existe-t-il un moyen d'y parvenir ?

6voto

Gordon Points 156415

Le constructeur et le destructeur de C auront la priorité sur le constructeur et le destructeur du trait lorsque la classe sera composée :

Un membre hérité d'une classe de base est remplacé par un membre inséré par un Trait. L'ordre de préséance est que les membres de la classe actuelle surchargent les méthodes Trait qui, en retour, remplacent les méthodes héritées.

Fuente: http://php.net/traits

En d'autres termes, supprimez le constructeur et le destructeur vides de C et le constructeur et le destructeur du trait seront utilisés. Il n'y a aucun moyen de faire fonctionner cela à la fois avec C et les traits, le constructeur et le destructeur, parce que les traits ne fonctionnent pas comme l'héritage normal.

En général, je déconseille de donner aux Traits leurs propres constructeurs ou destructeurs, car vous ne pouvez pas instancier les Traits. Vous instanciez à partir d'une classe ayant un Trait et cette classe devrait avoir le contrôle. Envisagez d'ajouter un onCreate() ou onDestroy() à la place du trait et les appeler à partir des méthodes magiques appropriées en C. Vous pourriez réaliser la même chose en aliasant le trait __construct en C, mais je pense que cela affaiblit la sémantique.

3voto

Aerendir Points 23

Vous devez définir un nom personnalisé pour les méthodes de la catégorie Trait . Vous pouvez ensuite appeler ces méthodes à partir de votre classe.

Comme les méthodes de la classe écrasent les méthodes de la classe Trait vous devez attribuer un nom différent aux méthodes de l'élément Trait :

class C
{
    use Audit {
        Audit::__construct as auditConstruct;
        Audit::__destruct as auditDestruct;
    }

    public function __construct()
    {
         $this->auditConstruct();
    }

    public function __destruct()
    {
         $this->auditDestruct();
    }
}

3voto

Cyborgv2 Points 31

Complément à Aeremdir Réponse de l'auteur : constructeurs hérités de la classe de base et traits multiples...

<?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();
?>

sous PHP 7.0.5 ce code résulte en...

C1::__construct() done
T1::__construct() done
T2::__construct() done
C2::__construct() done
0b10100011

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X