O PHP 8.1 finalmente adicionará suporte de linguagem para enums. Enums, abreviação de enumerações, são tipos que só podem ser instanciados com valores específicos. Eles são comumente encontrados em outras linguagens orientadas a objetos, mas antes exigiam soluções alternativas do ambiente do usuário para serem implementados em PHP.
Sintaxe básica
Esta é a aparência de um enum simples:
enum PostStatus & # 123; case Published; case InReview; case Draft; & # 125;
A palavra-chave case, anteriormente parte das instruções switch, é usada para delinear os valores específicos que o enum aceita. Os valores são referenciados da mesma maneira que as constantes de classe:
$ publicado = PostStatus :: Publicado;
Enums se comportam de maneira semelhante às classes e interfaces. Eles são totalmente compatíveis com o sistema de tipos, então você pode digitar a dica de que uma função só aceita um valor definido em um enum:
classe BlogPost & # 123; publicfunction __construct & # 40; public string $ Headline, public string $ Content, public PostStatus $ Status = PostStatus :: Rascunho & # 41; & # 123; & # 125; & # 125;
Aqui está um exemplo de uso da classe BlogPost:
// OK $ post = new BlogPost & # 40; ” Exemplo de postagem “, ” Um exemplo & quot ;, PostStatus :: Rascunho & # 41 ;; // TypeError: Argument # 3 ($ Status) deve ser do tipo PostStatus $ post = new BlogPost & # 40; ” Exemplo quebrado “, ” Um exemplo quebrado “, ” Enviado ” & # 41 ;;
A primeira instância funciona porque seu $ Status é um valor válido do enum PostStatus. No segundo caso, uma string simples é passada como $ Status, o que é proibido porque o valor deve ser definido em PostStatus.
Casos enum são representados como constantes no objeto enum. Isso significa que você pode usá-los como valores estáticos e como parte de expressões constantes. O construtor BlogPost mostra um caso enum sendo usado como um valor de parâmetro padrão, onde $ Status é automaticamente definido como Rascunho quando nenhum valor é fornecido pelo chamador.
Publicidade
Você pode acessar todos os valores disponíveis em um enum usando seu método de casos:
PostStatus :: cases & # 40; & # 41 ;; // [PostStatus :: Published, PostStatus :: InReview, PostStatus :: Draft]
Enums puros vs apoiados
O enum PostStatus acima é um enum puro. Ele contém apenas instruções de caso, sem dados extras. PHP também permite anexar um valor a casos enum, criando um enum apoiado.
enum PostStatus: string & # 123; case Published = ” S1 & quot ;; case InReview = ” S2 & quot ;; case Draft = ” S3 & quot ;; & # 125;
Aqui, o enum PostStatus foi modificado para criar um enum apoiado. A dica de tipo na definição do enum estipula que cada caso tem um valor de string atribuído a ele. Neste exemplo, estamos assumindo que cada status de postagem nomeada possui um identificador curto associado. Pode ser esse identificador que é salvo no banco de dados quando as postagens são persistidas.
Você pode acessar os valores apoiados por meio da propriedade value em instâncias de caso:
classe BlogPostRepository & # 123; publicfunction salvar & # 40; BlogPost $ Post & # 41 ;: void & # 123; $ this- > insert & # 40; ” blog_posts “, & # 91; ” headline ” = > $ Post- > Headline, & quot ; conteúdo ” = > $ Post- > Conteúdo, ” status ” = > $ Post- > Status- > valor & # 93; & # 41 ;; & # 125; & # 125; $ post = new BlogPost & quot ;, ” Demonstração & quot ;, PostStatus :: Publicado & # 41 ;; & # 40; new BlogPostRepository & # 40; & # 41; & # 41; – > salvar & # 40; $ post & # 41 ;;
Este exemplo definiria o valor do campo de status persistente para S1, com base na versão com backup do enum PostStatus mostrado acima.
Enums apoiados só aceitam strings e inteiros como valores. Também não é possível usar a cadeia de tipos de união | int. Além disso, cada caso precisa de um valor exclusivo – o exemplo a seguir não é permitido:
enum PostStatus: string & # 123; case Published = “S1”; case Draft = “S1″; & # 125;
Publicidade
O PHP fornece um método utilitário em enums para criar uma instância a partir de um valor apoiado:
// buscar a postagem do blog anterior no banco de dados // o ” status ” field = S1 $ status = PostStatus :: from & # 40; $ record & # 91; ” status ” & # 93; & # 41 ;;
O método from () hidratará instâncias de casos de valor. Neste exemplo, S1 é mapeado de volta para o caso Publicado e seu código recebe uma instância de PostStatus :: Publicado.
from () lança um ValueError se o valor de entrada for inválido; em cenários onde você sabe que o valor pode não ser utilizável, o método alternativo tryFrom () pode ser usado em seu lugar. Isso retorna nulo quando não há correspondência, em vez de lançar o erro.
Adicionando métodos a Enums
Como enums são baseados em classes, você também pode adicionar métodos a eles!
enum PostStatus & # 123; caso publicado; rascunho do caso; publicfunction isPubliclyAccessible & # 40; & # 41 ;: bool & # 123; return & # 40; $ this instanceof self :: Publicado & # 41 ;; & # 125; & # 125;
Isso permite que você mantenha o comportamento específico do caso em seu enum, em vez de duplicá-lo em sua base de código.
Enums também podem implementar interfaces:
enum PostStatus implementa PublicAccessGatable & # 123; caso publicado; rascunho do caso; publicfunction isPubliclyAccessible & # 40; & # 41 ;: bool & # 123; return & # 40; $ this instanceof self :: Publicado & # 41 ;; & # 125; & # 125;
Agora você pode passar uma instância PostStatus para qualquer coisa que aceite uma PublicAccessGatable:
classe UserAuthenticator & # 123; function shouldAllowAccess & # 40; PublicAccessGatable $ Resource & # 41 ;: bool & # 123; return & # 40; $ this- > User- > isAdmin & # 40; & # 41; || $ Resource- > isPubliclyAccessible & # 40; & # 41; & # 41 ;; & # 125; & # 125; $ auth = new UserAuthenticator & # 40; & # 41 ;; // obter uma postagem de blog do banco de dados se & # 40;! $ auth- > shouldAllowAccess & # 40; $ post- > Status & # 41; & # 41; & # 123; http_response_code & # 40; 403 & # 41 ;; & # 125;
Publicidade
Não há restrições sobre o que você pode fazer com os métodos enum – eles são métodos PHP regulares, afinal – mas, em geral, você espera que eles façam algum tipo de comparação com o caso da instância e, em seguida, retornem um valor estático. Enums podem usar características, então você pode extrair métodos existentes que você abstraiu desta forma também.
Você pode usar os métodos público, protegido e privado em enums, embora protegido e privado tenham o mesmo efeito. Os enums não podem se estender, então o privado é efetivamente redundante. Você também não pode adicionar um construtor ou destruidor. Métodos estáticos são suportados e podem ser chamados na classe enum ou em suas instâncias de caso.
Constantes
Enums também podem ter suas próprias constantes, como valores literais regulares ou uma referência a um caso de enum:
enum PostStatus & # 123; caso publicado; rascunho do caso; publicconst Live = self :: Published; publicconst PlainConstant = ” foobar & quot ;; & # 125;
Isso tem o potencial de criar confusão, pois a mesma sintaxe é usada para acessar casos (instâncias enum) e constantes:
$ publicado = PostStatus :: publicado; $ plain = PostStatus :: PlainConstant;
Apenas $ publicado satisfaria uma sugestão de tipo PostStatus, já que $ plain se refere a um valor escalar simples.
Quando usar Enums?
Enums são para ocasiões em que você precisa de flexibilidade no valor que uma variável pode assumir, mas apenas entre um conjunto predeterminado de casos possíveis.
Publicidade
A aula de postagem do blog que percorre esta postagem é um exemplo clássico. As postagens só podem estar em um de um conjunto conhecido de estados, mas o PHP não tinha uma maneira direta de fazer isso.
Em versões anteriores, você pode ter usado esta abordagem:
class PostStatus & # 123; const Published = 0; const Draft = 1; & # 125; class BlogPost & # 123; publicfunction __construct & # 40; public string $ Headline, public int $ Status & # 41; & # 123; & # 125; & # 125; $ post = new BlogPost & # 40; ” Meu título & quot ;, PostStatus :: Publicado & # 41 ;;
O problema aqui é que $ Status realmente aceita qualquer número inteiro, então a seguinte chamada seria perfeitamente válida:
$ post = new BlogPost & # 40; ” Meu título “, 9000 & # 41 ;;
Além disso, BlogPost e PostStatus são completamente separados – não há como alguém lendo o BlogPost aprender a gama de valores que $ Status realmente aceita. Embora esses problemas possam ser atenuados com o uso de dicas de tipo docblock adequadas ou “ enum falsa ” de terceiros; pacotes, todos eles estão adicionando camadas extras em torno de um conceito que outras linguagens de programação simplificam.
Adicionar enums nativos ao PHP é uma etapa que ajuda a completar o sistema de tipos da linguagem. Você pode finalmente digitar valores permissíveis de dicas de uma forma que mantenha todos na mesma página. Se você passar um valor inválido, receberá um erro de tempo de execução. Seu IDE pode ajudá-lo melhor a fornecer valores corretos, pois saberá que $ Status aceita apenas três opções, em vez de “ qualquer número inteiro. ”
Conclusão
Enums abordam alguns pontos comuns do desenvolvedor ao trabalhar em PHP. Eles tornam possível digitar a sugestão de que parâmetros, valores de retorno e propriedades devem fazer parte de um conjunto de opções predeterminadas.
Enums são entidades de base de código flexíveis que você pode manter simples na forma pura ou estender com valores de apoio, implementações de interface e métodos personalizados. Enums se comportam de maneira semelhante a objetos regulares na maioria dos casos e oferecem suporte a recursos de classe, como __call (), __invoke e :: class.
Publicidade
Você pode examinar enums com a nova função enum_exists () e a classe ReflectionEnum Reflection. Além disso, enums implementam duas novas interfaces, UnitEnum (no caso de enums puros) e BackedEnum (para enums com valores apoiados). Eles podem ser usados no código de estrutura genérica que funciona com qualquer enum. As interfaces não podem ser implementadas manualmente pelo código do userland.
Enums chegará ao PHP como parte da versão 8.1 em novembro de 2021. Eles já estão disponíveis nas compilações beta mais recentes. O PHP 8.1 também enviará vários outros recursos convenientes, incluindo propriedades somente leitura e tipos de interseção.