Maison > développement back-end > PHP8 > le corps du texte

Une grande explication des nouvelles fonctionnalités de PHP8.1 : propriétés en lecture seule propriétés en lecture seule

藏色散人
Libérer: 2023-02-17 12:12:01
original
3372 Les gens l'ont consulté

Cet article est traduit, adresse originale : https://stitcher.io/blog/php-81-readonly-properties

PHP 8.1 : Propriétés en lecture seule

Depuis de nombreuses années, j'utilise PHP pour écrire des objets et des valeurs de transfert de données Les objets deviennent très faciles. Prenons l'exemple d'un DTO en PHP 5.6 :

class BlogData
{
    /** @var string */
    private $title;
    
    /** @var Status */
    private $status;
    
    /** @var \DateTimeImmutable|null */
    private $publishedAt;
   
   /**
    * @param string $title 
    * @param Status $status 
    * @param \DateTimeImmutable|null $publishedAt 
    */
    public function __construct(
        $title,
        $status,
        $publishedAt = null
    ) {
        $this->title = $title;
        $this->status = $status;
        $this->publishedAt = $publishedAt;
    }
    
    /**
     * @return string 
     */
    public function getTitle()
    {
        return $this->title;    
    }
    
    /**
     * @return Status 
     */
    public function getStatus() 
    {
        return $this->status;    
    }
    
    /**
     * @return \DateTimeImmutable|null 
     */
    public function getPublishedAt() 
    {
        return $this->publishedAt;    
    }
}
Copier après la connexion

et comparez-le à l'équivalent en PHP 8.0 :

class BlogData
{
    public function __construct(
        private string $title,
        private Status $status,
        private ?DateTimeImmutable $publishedAt = null,
    ) {}
    
    public function getTitle(): string
    {
        return $this->title;    
    }
    
    public function getStatus(): Status 
    {
        return $this->status;    
    }
    
    public function getPublishedAt(): ?DateTimeImmutable
    {
        return $this->publishedAt;    
    }
}
Copier après la connexion

C'est assez différent, même si je pense qu'il y a quand même un gros problème : tous ces getters. Personnellement, je ne les utilise plus depuis PHP 8.0 et ses propriétés améliorées. Je préfère simplement utiliser des propriétés publiques plutôt que d'ajouter des getters :

class BlogData
{
    public function __construct(
        public string $title,
        public Status $status,
        public ?DateTimeImmutable $publishedAt = null,
    ) {}
}
Copier après la connexion

Les puristes orientés objet n'aiment pas cette approche : l'état interne d'un objet ne doit pas être directement exposé et ne peut certainement pas être modifié de l'extérieur.

Dans notre projet chez Spatie, nous avons une règle de guide de style interne selon laquelle les DTO et VO avec des propriétés publiques ne doivent pas être modifiés en externe ; une pratique qui semble bien fonctionner et nous le faisons depuis longtemps, aucun problème rencontré.

Cependant, oui ; je suis d’accord, il serait préférable que le langage garantisse que les propriétés publiques ne soient pas du tout annulées. Eh bien, PHP 8.1 a résolu tous ces problèmes en introduisant le mot-clé en lecture seule :

class BlogData
{
    public function __construct(
        public readonly string $title,
        public readonly Status $status,
        public readonly ?DateTimeImmutable $publishedAt = null,
    ) {}
}
Copier après la connexion

Ce mot-clé fait essentiellement ce que son nom suggère : une fois qu'une propriété est définie, elle ne peut plus être remplacée :

$blog = new BlogData(
    title: 'PHP 8.1: readonly properties', 
    status: Status::PUBLISHED, 
    publishedAt: now()
);
$blog->title = 'Another title';
Error: Cannot modify readonly property BlogData::$title
Copier après la connexion

Sachant que lorsqu'un objet est construit, il ne peut plus changer, offre un niveau de certitude et de tranquillité d'esprit lors de l'écriture du code : une série de changements de données imprévus ne peut tout simplement pas se reproduire.

Bien sûr, vous souhaitez toujours pouvoir copier les données vers le nouvel objet, et éventuellement modifier certaines propriétés au cours du processus. Nous verrons plus loin dans cet article comment procéder à l'aide de propriétés en lecture seule. Tout d’abord, examinons-les de plus près.

Voulez-vous en savoir plus sur PHP 8.1 ? Il existe un chemin vers PHP 8.1. Pendant les 10 prochains jours, vous recevrez un e-mail quotidien concernant une fonctionnalité nouvelle et existante de PHP 8.1, vous serez alors automatiquement désabonné afin de ne pas recevoir de spam ou d'e-mails de suivi. Abonnez-vous maintenant !

#Propriétés d'entrée uniquement

Les propriétés en lecture seule ne peuvent être utilisées qu'en combinaison avec des propriétés typées :

class BlogData
{
    public readonly string $title;
    
    public readonly $mixed;
}
Copier après la connexion

Cependant, vous pouvez utiliser Mixed comme indice de type :

class BlogData
{
    public readonly string $title;
    
    public readonly mixed $mixed;
}
Copier après la connexion

La raison de cette limitation est en omettant le type de propriété, null PHP définira automatiquement la valeur de la propriété si aucune valeur explicite n'est fournie dans le constructeur. Ce comportement, combiné à la lecture seule, peut entraîner une confusion inutile.

#Propriétés normales et propriétés promues

Vous avez vu des exemples des deux : la lecture seule peut être ajoutée sur les propriétés normales et les propriétés promues :

class BlogData
{
    public readonly string $title;
    
    public function __construct(
        public readonly Status $status, 
    ) {}
}
Copier après la connexion

#Aucune valeur par défaut

Les propriétés en lecture seule ne peuvent pas avoir de valeurs par défaut :

class BlogData
{
    public readonly string $title = 'Readonly properties';
}
Copier après la connexion

Autrement dit, à moins qu'il ne s'agisse de propriétés promues :

class BlogData
{
    public function __construct(
        public readonly string $title = 'Readonly properties', 
    ) {}
}
Copier après la connexion

Il est permis de promouvoir des propriétés car la valeur par défaut d'une propriété promue n'est pas utilisée comme valeur par défaut de la propriété de classe, mais s'applique uniquement aux paramètres du constructeur . Dans les coulisses, le code ci-dessus se traduira par :

class BlogData
{
    public readonly string $title;
    
    public function __construct(
        string $title = 'Readonly properties', 
    ) {
        $this->title = $title;
    }
}
Copier après la connexion

Vous pouvez voir comment la propriété réelle ne se voit pas attribuer de valeur par défaut. À propos, la raison pour laquelle les valeurs par défaut des propriétés en lecture seule ne sont pas autorisées est qu'elles ne sont pas différentes des constantes de cette forme.

#legacy

Aucune modification autorisée pour l'indicateur en lecture seule lors de l'héritage :

class Foo
{
    public readonly int $prop;
}
class Bar extends Foo
{
    public int $prop;
}
Copier après la connexion

Cette règle va dans les deux sens : l'indicateur en lecture seule ne peut pas être ajouté ou supprimé pendant l'héritage.

#La désactivation n'est pas autorisée

Une fois qu'une propriété en lecture seule est définie, vous ne pouvez pas la modifier, ni même la supprimer :

$foo = new Foo('value');
unset($foo->prop);
Copier après la connexion

#Réflexion

Il existe une nouvelle méthode, ainsi qu'un indicateur . ReflectionProperty::isReadOnly()ReflectionProperty::IS_READONLY

#Clone

Donc, si vous ne pouvez pas modifier les propriétés en lecture seule et que vous ne pouvez pas les supprimer, comment créer une copie d'un DTO ou d'un VO et modifier certaines de ses données ? Vous ne pouvez pas les cloner car vous ne pourrez pas écraser leurs valeurs. Il y avait en fait une idée de cloner avec une construction qui permettrait ce comportement à l'avenir, mais cela ne résoudrait pas notre problème pour le moment.

Eh bien, si vous comptez sur un peu de magie de réflexion, vous pouvez copier un objet avec une propriété en lecture seule modifiée. En créant un objet sans appeler son constructeur (cela peut être fait en utilisant la réflexion), puis en copiant manuellement chaque propriété - en écrasant parfois sa valeur - vous pouvez réellement "cloner" un objet et modifier ses propriétés en lecture seule.

J'ai fait un petit package pour ce faire et ça ressemble à ceci :

class BlogData
{
    use Cloneable;
    public function __construct(
        public readonly string $title,
    ) {}
}
$dataA = new BlogData('Title');
$dataB = $dataA->with(title: 'Another title');
Copier après la connexion

J'ai en fait écrit un article de blog dédié expliquant les mécanismes derrière tout cela que vous pouvez lire ici.

Il s’agit donc de propriétés en lecture seule. Je pense qu'ils constituent une fonctionnalité intéressante si vous travaillez sur un projet qui traite de nombreux DTO et VO et vous oblige à gérer soigneusement le flux de données dans tout votre code. Les objets immuables avec des propriétés en lecture seule sont très utiles à cet égard.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!