mirror of
https://github.com/php/doc-pt_br.git
synced 2026-03-23 22:52:12 +01:00
390 lines
11 KiB
XML
390 lines
11 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: 0f14761ba340c6e49797706ac3f0cf1147d97253 Maintainer: leonardolara Status: ready --><!-- CREDITS: marcosmarcolin, adiel, leonardolara -->
|
||
<chapter xml:id="language.attributes" xmlns="http://docbook.org/ns/docbook">
|
||
<title>Atributos</title>
|
||
<sect1 xml:id="language.attributes.overview">
|
||
<title>Visão geral dos atributos</title>
|
||
<?phpdoc print-version-for="attributes"?>
|
||
|
||
<para>
|
||
Os atributos PHP fornecem metadados estruturados e legíveis por máquina para classes, métodos,
|
||
funções, parâmetros, propriedades e constantes. Eles podem ser inspecionados no momento da execução
|
||
por meio da <link linkend="book.reflection">API Reflection</link>, permitindo comportamento
|
||
dinâmico sem modificar o código. Os atributos fornecem uma maneira declarativa de anotar
|
||
código com metadados.
|
||
</para>
|
||
<para>
|
||
Atributos permitem o desacoplamento da implementação de um recurso de seu uso. Enquanto
|
||
interfaces definem estrutura ao impor métodos, atributos fornecem metadados em vários
|
||
elementos, incluindo métodos, funções, propriedades e constantes. Diferentemente de interfaces,
|
||
que impõem implementações de métodos, atributos anotam código sem alterar sua estrutura.
|
||
</para>
|
||
<para>
|
||
Atributos podem complementar ou substituir métodos de interface opcionais fornecendo metadados em vez de
|
||
estrutura imposta. Considere uma interface <literal>ActionHandler</literal> que representa uma
|
||
operação em um aplicativo. Algumas implementações podem exigir uma etapa de configuração, enquanto outras não.
|
||
Em vez de forçar todas as classes que implementam <literal>ActionHandler</literal> a definir um
|
||
método <literal>setUp()</literal>, um atributo pode indicar requisitos de configuração. Essa abordagem
|
||
aumenta a flexibilidade, permitindo que os atributos sejam aplicados várias vezes quando necessário.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Implementando métodos opcionais de uma interface com Atributos</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
interface ActionHandler
|
||
{
|
||
public function execute();
|
||
}
|
||
|
||
#[Attribute]
|
||
class SetUp {}
|
||
|
||
class CopyFile implements ActionHandler
|
||
{
|
||
public string $fileName;
|
||
public string $targetDirectory;
|
||
|
||
#[SetUp]
|
||
public function fileExists()
|
||
{
|
||
if (!file_exists($this->fileName)) {
|
||
throw new RuntimeException("Arquivo não existe");
|
||
}
|
||
}
|
||
|
||
#[SetUp]
|
||
public function targetDirectoryExists()
|
||
{
|
||
if (!file_exists($this->targetDirectory)) {
|
||
mkdir($this->targetDirectory);
|
||
} elseif (!is_dir($this->targetDirectory)) {
|
||
throw new RuntimeException("Diretório de destino $this->targetDirectory não é um diretório");
|
||
}
|
||
}
|
||
|
||
public function execute()
|
||
{
|
||
copy($this->fileName, $this->targetDirectory . '/' . basename($this->fileName));
|
||
}
|
||
}
|
||
|
||
function executeAction(ActionHandler $actionHandler)
|
||
{
|
||
$reflection = new ReflectionObject($actionHandler);
|
||
|
||
foreach ($reflection->getMethods() as $method) {
|
||
$attributes = $method->getAttributes(SetUp::class);
|
||
|
||
if (count($attributes) > 0) {
|
||
$methodName = $method->getName();
|
||
|
||
$actionHandler->$methodName();
|
||
}
|
||
}
|
||
|
||
$actionHandler->execute();
|
||
}
|
||
|
||
$copyAction = new CopyFile();
|
||
$copyAction->fileName = "/tmp/foo.jpg";
|
||
$copyAction->targetDirectory = "/home/user";
|
||
|
||
executeAction($copyAction);
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.attributes.syntax">
|
||
<title>Sintaxe de Atributo</title>
|
||
|
||
<para>
|
||
A sintaxe de atributo consiste em vários componentes-chave. Uma declaração de atributo
|
||
começa com <literal>#[</literal> e termina com
|
||
<literal>]</literal>. Dentro, um ou mais atributos podem ser listados,
|
||
separados por vírgulas. O nome do atributo pode ser não qualificado, qualificado,
|
||
ou totalmente qualificado, conforme descrito em <link linkend="language.namespaces.basics">Usando Namespaces Básicos</link>.
|
||
Argumentos para o atributo são opcionais e colocados entre parênteses
|
||
<literal>()</literal>. Argumentos podem ser apenas valores literais ou expressões
|
||
constantes. Tanto a sintaxe de argumento posicional quanto a de argumento nomeado são suportadas.
|
||
</para>
|
||
|
||
<para>
|
||
Nomes de atributos e seus argumentos são resolvidos para uma classe, e os argumentos
|
||
são passados para seu construtor quando uma instância do atributo é solicitada
|
||
por meio da API Reflection. Portanto, é recomendado introduzir uma classe
|
||
para cada atributo.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Sintaxe de Atributo</title>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
// a.php
|
||
namespace MyExample;
|
||
|
||
use Attribute;
|
||
|
||
#[Attribute]
|
||
class MyAttribute
|
||
{
|
||
const VALUE = 'value';
|
||
|
||
private $value;
|
||
|
||
public function __construct($value = null)
|
||
{
|
||
$this->value = $value;
|
||
}
|
||
}
|
||
|
||
// b.php
|
||
|
||
namespace Another;
|
||
|
||
use MyExample\MyAttribute;
|
||
|
||
#[MyAttribute]
|
||
#[\MyExample\MyAttribute]
|
||
#[MyAttribute(1234)]
|
||
#[MyAttribute(value: 1234)]
|
||
#[MyAttribute(MyAttribute::VALUE)]
|
||
#[MyAttribute(array("key" => "value"))]
|
||
#[MyAttribute(100 + 200)]
|
||
class Thing
|
||
{
|
||
}
|
||
|
||
#[MyAttribute(1234), MyAttribute(5678)]
|
||
class AnotherThing
|
||
{
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</sect1>
|
||
|
||
|
||
<sect1 xml:id="language.attributes.reflection">
|
||
<title>Lendo Atributos com a API Reflection</title>
|
||
|
||
<para>
|
||
Para acessar atributos de classes, métodos, funções, parâmetros, propriedades
|
||
e constantes de classe, use o método <function>getAttributes</function> fornecido
|
||
pela API Reflection. Este método retorna um array de instâncias de <classname>ReflectionAttribute</classname>.
|
||
Essas instâncias podem ser consultadas para o nome do atributo, argumentos e
|
||
podem ser usadas para instanciar o atributo representado.
|
||
</para>
|
||
|
||
<para>
|
||
Separar a representação do atributo refletido de sua instância real fornece mais
|
||
controle sobre o tratamento de erros, como classes de atributos ausentes, argumentos digitados incorretamente
|
||
ou valores ausentes. Objetos da classe de atributo são instanciados somente após chamar
|
||
<function>ReflectionAttribute::newInstance</function>, garantindo que a validação do argumento
|
||
ocorra naquele ponto.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Lendo Atributos Usando a API Reflection</title>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
#[Attribute]
|
||
class MyAttribute
|
||
{
|
||
public $value;
|
||
|
||
public function __construct($value)
|
||
{
|
||
$this->value = $value;
|
||
}
|
||
}
|
||
|
||
#[MyAttribute(value: 1234)]
|
||
class Thing
|
||
{
|
||
}
|
||
|
||
function dumpAttributeData($reflection) {
|
||
$attributes = $reflection->getAttributes();
|
||
|
||
foreach ($attributes as $attribute) {
|
||
var_dump($attribute->getName());
|
||
var_dump($attribute->getArguments());
|
||
var_dump($attribute->newInstance());
|
||
}
|
||
}
|
||
|
||
dumpAttributeData(new ReflectionClass(Thing::class));
|
||
/*
|
||
string(11) "MyAttribute"
|
||
array(1) {
|
||
["value"]=>
|
||
int(1234)
|
||
}
|
||
object(MyAttribute)#3 (1) {
|
||
["value"]=>
|
||
int(1234)
|
||
}
|
||
*/
|
||
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
Em vez de iterar sobre todos os atributos na instância de reflexão,
|
||
você pode recuperar apenas aqueles de uma classe de atributo específica passando
|
||
o nome da classe de atributo como um argumento.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Lendo Atributos Específicos Usando a API Reflection</title>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
function dumpMyAttributeData($reflection) {
|
||
$attributes = $reflection->getAttributes(MyAttribute::class);
|
||
|
||
foreach ($attributes as $attribute) {
|
||
var_dump($attribute->getName());
|
||
var_dump($attribute->getArguments());
|
||
var_dump($attribute->newInstance());
|
||
}
|
||
}
|
||
|
||
dumpMyAttributeData(new ReflectionClass(Thing::class));
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.attributes.classes">
|
||
<title>Declarando Classes de Atributos</title>
|
||
|
||
<para>
|
||
É recomendado definir uma classe separada para cada atributo.
|
||
No caso mais simples, uma classe vazia com a declaração <literal>#[Attribute]</literal>
|
||
é suficiente. O atributo pode ser importado do namespace global usando uma
|
||
declaração <literal>use</literal>.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Classe de Atributo Simples</title>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace Example;
|
||
|
||
use Attribute;
|
||
|
||
#[Attribute]
|
||
class MyAttribute
|
||
{
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
Para restringir os tipos de declarações às quais um atributo pode ser aplicado,
|
||
passe uma máscara de bits como o primeiro argumento para a declaração
|
||
<literal>#[Attribute]</literal>.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Usando a especificação de destino para restringir onde os atributos podem ser usados</title>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace Example;
|
||
|
||
use Attribute;
|
||
|
||
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
|
||
class MyAttribute
|
||
{
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
|
||
<para>
|
||
Declarar <classname>MyAttribute</classname> em outro tipo agora lançará uma exceção durante a
|
||
chamada para <function>ReflectionAttribute::newInstance</function>
|
||
</para>
|
||
</example>
|
||
|
||
<para>Os seguintes alvos podem ser especificados:</para>
|
||
|
||
<simplelist>
|
||
<member><constant>Attribute::TARGET_CLASS</constant></member>
|
||
<member><constant>Attribute::TARGET_FUNCTION</constant></member>
|
||
<member><constant>Attribute::TARGET_METHOD</constant></member>
|
||
<member><constant>Attribute::TARGET_PROPERTY</constant></member>
|
||
<member><constant>Attribute::TARGET_CLASS_CONSTANT</constant></member>
|
||
<member><constant>Attribute::TARGET_PARAMETER</constant></member>
|
||
<member><constant>Attribute::TARGET_ALL</constant></member>
|
||
</simplelist>
|
||
|
||
<para>
|
||
Por padrão, um atributo só pode ser usado uma vez por declaração. Para permitir
|
||
que um atributo seja repetível, especifique-o na máscara de bits da
|
||
declaração <literal>#[Attribute]</literal> usando o sinalizador
|
||
<constant>Attribute::IS_REPEATABLE</constant>.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Usando IS_REPEATABLE para permitir o atributo em uma declaração várias vezes</title>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace Example;
|
||
|
||
use Attribute;
|
||
|
||
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::IS_REPEATABLE)]
|
||
class MyAttribute
|
||
{
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
|
||
</example>
|
||
</sect1>
|
||
</chapter>
|
||
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|