PHP 8.1.9 Released!

Backed enums

Por padrão, os Casos não possuem um equivalente escalar. Eles são apenas objetos singleton. No entanto, existem muitos casos em que um Caso Enumerado precisa ser capaz de fazer fazer uma conversão de ida e volta para um banco de dados ou um armazenamento de dados semelhante, então ter um escalar embutido (e, portanto, trivialmente serializável) equivalente definido intrinsecamente é útil.

Para definir um equivalente escalar para uma Enumeração, a sintaxe é a seguinte:

<?php
enum Naipe
string
{
    case 
Copas 'C';
    case 
Ouros 'O';
    case 
Paus 'P';
    case 
Espadas 'E';
}
?>

Um caso que possui um equivalente escalar é chamado de Backed Case, sendo "Backed" no sentido de lastreado, suportado, por um valor mais simples. Uma Enum que possui todos Casos Lastreados é chamada Backed Enum. Uma Backed Enum pode conter apenas Backed Case. Uma Enum Pura pode conter apenas Casos Puros.

Uma Backed Enum pode associar valores de tipos int ou string, e uma determinada enumeração suporta apenas um único tipo de cada vez (isto é, sem união de int|string). Se uma enumeração for marcada como tendo um equivalente escalar, então todos os casos devem possuir um escalar equivalente único definido explicitamente. Não existem equivalentes escalares gerados automaticamente (p. ex.: inteiros sequenciais). Casos lastreados devem ser únicos; dois casos enum lastreados não podem ter o mesmo equivalente escalar. No entanto, uma constante pode se referir a um caso, efetivamente criando um apelido. Veja Constantes de enumeração.

Valores equivalentes devem ser literais ou expressões literais. Constantes e expressões constantes não são suportadas. Isto é, 1 + 1 é permitido, mas 1 + SOME_CONST não é.

Backed Cases possuem uma propriedade somente leitura adicional, value, que é o valor especificado na definição.

<?php
print Naipe::Paus->value;
// Imprime "P"
?>

Para impor a propriedade value como somente leitura, uma variável não pode ser atribuída como uma referência para ela. Isto é, o seguinte lança um erro:

<?php
$naipe 
Naipe::Paus;
$ref = &$naipe->value;
// Error: Cannot acquire reference to property Naipe::$value
?>

Backed Enums implementam uma interface interna BackedEnum, que expõe dois métodos adicionais:

  • from(int|string): self recebe uma escalar e retornará o Caso Enum correspondente. Se um não for encontrado, ela lançará um ValueError. Isso é útil principalmente nas situações somente valores previstos são permitidos e um valor enum ausente deve ser considerado um erro de interrupção de aplicação.
  • tryFrom(int|string): ?self recebe uma escalar e retornará o Caso Enum correspondente. Se um não for encontrado, ela retornará null. Isso é útil principalmente em casos onde o escalar de entrada não é confiável e o chamador quer implementar sua própria lógica de manipulação de erros ou de valor padrão.

Os métodos from() e tryFrom() seguem as regras padrão de tipagem fraca/forte. No modo de tipagem fraca, passar um inteiro ou string é aceitável e o sistema irá coagir o valor de acordo. Passar um float também irá funcionar e será convertido. No modo de tipagem estrita, passar um inteiro para from() em uma enum associada a strings (ou vice-versa) irá resultar em um TypeError, assim como um float irá lançar um erro em todas as circunstâncias. Todos os outros tipos de parâmetro lançarão um TypeError em ambos os modos.

<?php
$registro 
obter_coisas_do_banco_de_dados($id);
print 
$registro['naipe'];

$naipe Naipe::from($registro['naipe']);
// Dados inválidos lançam um ValueError: "X" is not a valid scalar value for enum "Naipe"
print $naipe->value;

$naipe Naipe::tryFrom('A') ?? Naipe::Espadas;
// Dados invalidos retornam null, então Naipe::Espadas em seu lugar.
print $naipe->value;
?>

Definir manualmente um método from() ou tryFrom() em uma Backed Enum irá resultar em um erro fatal.

add a note

User Contributed Notes 1 note

up
2
ilovetobeanonymous at protonmail dot com
25 days ago
You want to add some constants in your Enum cases? You can use class constants !
Here's an example :
class Something
{
    const PARENT = 'parent';
}
enum MyEnum:string
{
    case firstChild = Something::PARENT . '_child1';
    case secondChild = Something::PARENT . '_child2';
   
}
echo MyEnum::firstChild->value; //print"parent_child1"
To Top