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 readonly
palavra-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 User
classe com a $username
propriedade 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 $username
vez ao criar um novo User
objeto como este:
$user = new User('joe','secure');
Linguagem de código: PHP ( php )
Se você tentar alterar a $username
propriedade depois disso, receberá um erro:
$user->username = 'john';
Linguagem de código: PHP ( php )
Erro:
Fatal error: Uncaught Error: Cannot modify readonly property User::$username
Linguagem de código: PHP ( php )
O PHP só permite inicializar a $username
propriedade 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 $username
propriedade 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 scope
Linguagem 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::$username
Linguagem 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:
NULL
Linguagem de código: texto simples ( texto simples )
Neste exemplo, o valor da $username
propriedade é null
o 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 readonly
palavra-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 type
Linguagem 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 UserProfile
classe que tenha duas propriedades name
e 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 User
classe que possui uma propriedade cujo tipo é um objeto da UserProfile
classe:
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 User
objeto 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 User
classe. 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
readonly
palavra-chave em uma propriedade digitada para tornar a propriedade somente leitura.