Propriedades somente leitura do PHP

Resumo : neste tutorial, você aprenderá sobre as propriedades readonly do PHP que só podem ser inicializadas uma vez.

Introdução às propriedades somente leitura do PHP

O PHP 8.1 introduziu as propriedades da classe somente leitura. As propriedades somente leitura permitem definir propriedades que só podem ser inicializadas uma vez dentro da classe.

Para definir uma propriedade somente leitura, você usa a readonlypalavra-chave em uma propriedade digitada :

<?php


class MyClass
{
    private readonly type propertyName;
}Linguagem de código:  PHP  ( php )

Ou

<?php


class MyClass
{
    public function __construct(private readonly type propertyName)
    {
    }
}Linguagem de código:  PHP  ( php )

Por exemplo, o seguinte define uma Userclasse com a $usernamepropriedade somente leitura:

<?php


class User
{
    public readonly string $username;

    public function __construct(string $username)
    {
        $this->username = $username;
    }
}Linguagem de código:  PHP  ( php )

Neste exemplo, você só pode inicializar uma $usernamevez ao criar um novo Userobjeto como este:

$user = new User('joe','secure');Linguagem de código:  PHP  ( php )

Se você tentar alterar a $usernamepropriedade depois disso, receberá um erro:

$user->username = 'john';Linguagem de código:  PHP  ( php )

Erro:

Fatal error: Uncaught Error: Cannot modify readonly property User::$usernameLinguagem de código:  PHP  ( php )

O PHP só permite inicializar a $usernamepropriedade de dentro da própria classe, seja do construtor ou de um método.

O exemplo a seguir também causa um erro porque tenta inicializar a $usernamepropriedade fora da classe User:

<?php


class User
{
    public readonly string $username;
}

$user = new User();
$user->username = 'joe';Linguagem de código:  PHP  ( php )

Erro:

Fatal error: Uncaught Error: Cannot initialize readonly property User::$username from global scopeLinguagem de código:  texto simples  ( texto simples )

Para consertar, você pode adicionar um construtor como o exemplo acima. Alternativamente, você pode definir um método para inicializar a propriedade readonly de dentro da classe da seguinte maneira:

<?php


class User
{
    public readonly string $username;
    public string $password;

    public function setUsername(string $username): void
    {
        $this->username = $username;
    }
    
}

$user = new User();
$user->setUsername('joe');Linguagem de código:  PHP  ( php )

Observe que se você chamar o setUsername()método uma segunda vez, receberá um erro porque ele modifica a propriedade username que já foi inicializada.

<?php


class User
{
    public readonly string $username;
    public string $password;

    public function setUsername(string $username): void
    {
        $this->username = $username;
    }
    
}

$user = new User();
$user->setUsername('joe');
$user->setUsername('john');Linguagem de código:  PHP  ( php )

Erro:

Fatal error: Uncaught Error: Cannot modify readonly property User::$usernameLinguagem de código:  texto simples  ( texto simples )

Propriedades somente leitura e digitadas

Uma propriedade sem tipo tem o valor padrão de null. Por exemplo:

<?php

class User
{
    public $username;
}

$user = new User();
var_dump($user->username);Linguagem de código:  PHP  ( php )

Saída:

NULLLinguagem de código:  texto simples  ( texto simples )

Neste exemplo, o valor da $usernamepropriedade é nullo padrão até que você atribua um valor a ela.

Por causa disso, o PHP suporta somente leitura em uma propriedade digitada. Se você tentar usar a readonlypalavra-chave com uma propriedade sem tipo, receberá um erro. Por exemplo:

<?php

class User
{
    public readonly $username;
}
Linguagem de código:  PHP  ( php )

Erro:

Fatal error: Readonly property User::$username must have typeLinguagem de código:  texto simples  ( texto simples )

Mutabilidade

Uma propriedade somente leitura não garante a imutabilidade dos objetos. Vejamos o exemplo a seguir.

Primeiro, defina uma UserProfileclasse que tenha duas propriedades namee phone:

<?php

class UserProfile
{
    public function __construct(private string $name, private string $phone)
    {
    }
    public function changePhone(string $phone)
    {
        $this->phone = $phone;
    }
}Linguagem de código:  PHP  ( php )

Segundo, defina a Userclasse que possui uma propriedade cujo tipo é um objeto da UserProfileclasse:

class User
{
    private readonly string $username;
    private readonly UserProfile $profile;

    public function __construct(string $username)
    {
        $this->username = $username;
    }

    public function setProfile(UserProfile $profile)
    {
        $this->profile = $profile;
    }

    public function profile(): UserProfile
    {
        return $this->profile;
    }
}Linguagem de código:  PHP  ( php )

Terceiro, crie um Userobjeto e atribua um perfil a ele:

$user = new User('joe');
$user->setProfile(new UserProfile('Joe Doe','(408)-555-6666'));Linguagem de código:  PHP  ( php )

The $profileé uma propriedade somente leitura da Userclasse. E você pode inicializá-lo uma vez. No entanto, você pode alterar as propriedades de uma propriedade somente leitura como esta:

$user->profile()->changePhone('(408)-999-9999');
var_dump($user->profile());Linguagem de código:  PHP  ( php )

Saída:

object(UserProfile)#2 (2) {
  ["name":"UserProfile":private]=>  string(7) "Joe Doe"
  ["phone":"UserProfile":private]=>  string(14) "(408)-999-9999"
}Linguagem de código:  texto simples  ( texto simples )

Junte tudo:

<?php

class UserProfile
{
    public function __construct(private string $name, private string $phone)
    {
    }
    public function changePhone(string $phone)
    {
        $this->phone = $phone;
    }
}

class User
{
    private readonly string $username;
    private readonly UserProfile $profile;

    public function __construct(string $username)
    {
        $this->username = $username;
    }

    public function setProfile(UserProfile $profile)
    {
        $this->profile = $profile;
    }

    public function profile(): UserProfile
    {
        return $this->profile;
    }
}


$user = new User('joe');
$user->setProfile(new UserProfile('Joe Doe','(408)-555-6666'));
$user->profile()->changePhone('(408)-999-9999');
var_dump($user->profile());
Linguagem de código:  PHP  ( php )

Resumo

  • Uma propriedade somente leitura pode ser inicializada uma vez dentro da classe.
  • Use a readonlypalavra-chave em uma propriedade digitada para tornar a propriedade somente leitura.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *