Constructeurs et destructeurs

Constructeur

__construct ( mixed ...$values = "" ) : void

PHP permet aux développeurs de déclarer des constructeurs pour les classes. Les classes qui possèdent une méthode constructeur appellent cette méthode à chaque création d'une nouvelle instance de l'objet, ce qui est intéressant pour toutes les initialisations dont l'objet a besoin avant d'être utilisé.

Note: Les constructeurs parents ne sont pas appelés implicitement si la classe enfant définit un constructeur. Si vous voulez utiliser un constructeur parent, il sera nécessaire de faire appel à parent::__construct() depuis le constructeur enfant. Si l'enfant ne définit pas un constructeur alors il peut être hérité de la classe parent, exactement de la même façon qu'une méthode le serait (si elle n'a pas été déclarée comme privée).

Exemple #1 Constructeur lors de l'héritage

<?php
class BaseClass {
    function 
__construct() {
        print 
"Dans le constructeur de BaseClass\n";
    }
}

class 
SubClass extends BaseClass {
    function 
__construct() {
        
parent::__construct();
        print 
"Dans le constructeur de SubClass\n";
    }
}

class 
OtherSubClass extends BaseClass {
    
// Constructeur hérité de BaseClass
}

// Dans le constructeur de BaseClass
$obj = new BaseClass();

// Dans le constructeur de BaseClass
// Dans le constructeur de SubClass
$obj = new SubClass();

// Dans le constructeur de BaseClass
$obj = new OtherSubClass();
?>

À la différence des autres méthodes, __construct() est exclus des règles de compatibilités des signatures usuel quand elle est étendue.

Les constructeurs sont des méthodes ordinaires qui sont appelées lors de l'instanciation de leur objet correspondant. Par conséquent, ils peuvent définir un nombre arbitraire d'arguments, qui peuvent être requis, avoir un type, et peuvent avoir une valeur par défaut. Les arguments d'un constructeur sont appelés en plaçant les arguments dans des parenthèses après le nom de la classe.

Exemple #2 Utiliser les arguments d'un constructeur

<?php
class Point {
    protected 
int $x;
    protected 
int $y;

    public function 
__construct(int $xint $y 0) {
        
$this->$x;
        
$this->$y;
    }
}

// Pass both parameters.
$p1 = new Point(45);
// Pass only the required parameter. $y will take its default value of 0.
$p2 = new Point(4);
// With named parameters (as of PHP 8.0):
$p3 = new Point(y5x4);
?>

Si une classe n'a pas de constructeur, ou le constructeur n'a pas d'arguments requis, les parenthèses peuvent être omit.

Style ancien des constructeurs

Antérieur à PHP 8.0.0, les classes dans le nom d'espace global interpréteront une méthode qui à la même nom que la classe comme un constructeur de style ancien. Cette syntaxe est obsolète, et résultera en une erreur E_DEPRECATED mais appellera quand même cette fonction comme un constructeur. Si __construct() et une méthode du même nom sont définie, __construct() sera appelé.

Les classes dans les espaces de nom, ou toute classe à partir de PHP 8.0.0, une méthode du même nom que la classe n'a jamais de signification particulière.

Toujours utiliser __construct() dans du nouveau code.

Promotion du Constructeur

À partir de PHP 8.0.0, les paramètres du constructeur peuvent être promu pour correspondre à une propriété de l'objet. Il est très commun pour les paramètres d'un constructeur d'être assigné à une propriété sans effectuer d'opérations dessus. La promotion du constructeur fournie un raccourci pour ce cas d'utilisation. L'exemple ci-dessus peut être réécrit de la façon suivante.

Exemple #3 Utilisant la promotion de propriété de constructeur

<?php
class Point {
    public function 
__construct(protected int $x, protected int $y 0) {
    }
}

Quand un argument de constructeur inclus un modificateur de visibilité, PHP l'interprétera comme une propriété d'objet et un argument du constructeur, et assigne la valeur de l'argument à la propriété. Le corps du constructeur peut être alors vide ou peut contenir d'autres déclarations. Toutes déclarations additionnelles seront exécuté apr_s que la valeur de l'argument a été assigné à leur propriétés correspondantes.

Tous les arguments ne doivent pas être promu. Il est possible de mélanger et assortir les arguments promu et non-promu, dans n'importe quel ordre. Les arguments promu n'ont aucun impact sur du code appellant le constructeur.

Note:

Les propriétés d'objet ne peuvent être typé callable à cause des ambiguïtés du moteur que ceci introduirait. Ainsi, les arguments promu, ne peuvent pas non plus être typé callable. Cependant, toute autre déclaration de type est permis.

Note:

Les attributs placé sur un argument de constructeur promu seront reproduit à la fois sur la propriété ainsi que sur l'argument.

Méthode de création statique

PHP supporte uniquement un constructeur unique par classe. Cependant, dans certains cas il peut être désirable de permettre à un objet d'être construit de manière différente avec des entrées différentes. La façon recommandé de faire ceci est en utilisant des méthodes statiques comme une enveloppe du constructeur.

Exemple #4 Utilisant la création via une méthode statique

<?php
class Product {

    private ?
int $id;
    private ?
string $name;

    private function 
__construct(?int $id null, ?string $name null) {
        
$this->id $id;
        
$this->name $name;
    }

    public static function 
fromBasicData(int $idstring $name): static {
        
$new = new static($id$name);
        return 
$new;
    }

    public static function 
fromJson(string $json): static {
        
$data json_decode($json);
        return new static(
$data['id'], $data['name']);
    }

    public static function 
fromXml(string $xml): static {
        
// Logique personnalisé.
        
$data convert_xml_to_array($xml);
        
$new = new static();
        
$new->id $data['id'];
        
$new->name $data['name'];
        return 
$new;
    }
}

$p1 Product::fromBasicData(5'Widget');
$p2 Product::fromJson($some_json_string);
$p3 Product::fromXml($some_xml_string);

Le constructeur peut être rendu privé ou protégé pour empêcher son appel depuis l'extérieur. Dans ce cas, seul une méthode statique sera capable d'instancier la classe. Car elles sont dans la même définition de classe elles ont accès aux méthodes privées, même dans une instance différente de l'objet. Un constructeur privé est optionnel et peut ou pas faire de sens en fonction du cas d'utilisation.

Les trois méthodes statiques publique démontrent alors des manières différentes d'instancier l'objet.

  • fromBasicData() prend les paramètres exacte qui sont nécessaire, puis créé l'objet en appellant le constructeur puis retournant le résultat.
  • fromJson() accepte une chaîne de caractère JSON et fait du pré-traitement sur lui même pour ce convertir dans le format désiré par le constructeur. Elle retourne alors le nouvel objet.
  • fromXml() accepte une chaîne de caractère XML, fait du pré-traitement, puis créé un objet brut. Le constructeur est appelé, mais comme tout les paramètres sont optionnels la méthode les ignores. Elle assigne alors les valeurs aux propriétés de l'objet directement avant de retourner le résultat.

Dans les trois cas, le mot clé static est traduit en le nom de la classe dont le code y est. Dans ce cas, Product.

Destructeur

__destruct ( ) : void

PHP possède un concept de destructeur similaire à celui d'autres langages orientés objet, comme le C++. La méthode destructeur est appelée dès qu'il n'y a plus de référence sur un objet donné, ou dans n'importe quel ordre pendant la séquence d'arrêt.

Exemple #5 Exemple avec un Destructeur

<?php

class MyDestructableClass 
{
    function 
__construct() {
        print 
"In constructor\n";
    }

    function 
__destruct() {
        print 
"Destroying " __CLASS__ "\n";
    }
}

$obj = new MyDestructableClass();

Tout comme le constructeur, le destructeur parent ne sera pas appelé implicitement par le moteur. Pour exécuter le destructeur parent, vous devez appeler explicitement la fonction parent::__destruct dans le corps du destructeur. Tout comme les constructeurs, une classe enfant peut hériter du destructeur du parent s'il n'en implémente pas un lui même.

Le destructeur sera appelé même si l'exécution du script est stoppée en utilisant la fonction exit(). Appeler la fonction exit() dans un destructeur empêchera l'exécution des routines d'arrêt restantes.

Note:

Les destructeurs appelés durant l'arrêt du script sont dans une situation où les en-têtes HTTP ont déjà été envoyés. Le dossier de travail dans la phase d'arrêt du script peut être différent avec certaines APIs (e.g. Apache).

Note:

Tenter de lancer une exception depuis un destructeur (appelé à la fin du script) entraine une erreur fatale.