mirror of
https://github.com/php/doc-fr.git
synced 2026-03-23 22:52:18 +01:00
387 lines
11 KiB
XML
387 lines
11 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: 0f14761ba340c6e49797706ac3f0cf1147d97253 Maintainer: pierrick Status: ready -->
|
|
<!-- Reviewed: no -->
|
|
<chapter xml:id="language.attributes" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Attributs</title>
|
|
<sect1 xml:id="language.attributes.overview">
|
|
<title>Aperçu des attributs</title>
|
|
<?phpdoc print-version-for="attributes"?>
|
|
|
|
<para>
|
|
Les attributs PHP fournissent des métadonnées structurées et lisibles par machine pour les classes, méthodes,
|
|
fonctions, paramètres, propriétés et constantes. Ils peuvent être inspectés à l'exécution
|
|
via l'<link linkend="book.reflection">API de réflexion</link>, permettant un comportement dynamique
|
|
sans modifier le code. Les attributs offrent un moyen déclaratif d'annoter le code avec des métadonnées.
|
|
</para>
|
|
<para>
|
|
Les attributs permettent de découpler l'implémentation d'une fonctionnalité de son utilisation.
|
|
Alors que les interfaces définissent une structure en imposant des méthodes, les attributs
|
|
fournissent des métadonnées sur plusieurs éléments, y compris les méthodes, fonctions,
|
|
propriétés et constantes. Contrairement aux interfaces, qui imposent l'implémentation de méthodes,
|
|
les attributs annotent le code sans en modifier la structure.
|
|
</para>
|
|
<para>
|
|
Les attributs peuvent compléter ou remplacer des méthodes d'interface optionnelles en fournissant
|
|
des métadonnées plutôt qu'une structure imposée. Prenons une interface <literal>ActionHandler</literal>
|
|
qui représente une opération dans une application. Certaines implémentations peuvent nécessiter une
|
|
étape d'initialisation, tandis que d'autres non. Plutôt que d'obliger toutes les classes implémentant
|
|
<literal>ActionHandler</literal> à définir une méthode <literal>setUp()</literal>, un attribut peut
|
|
indiquer les besoins en initialisation. Cette approche augmente la flexibilité en permettant
|
|
d'appliquer les attributs plusieurs fois si nécessaire.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Implémentation de méthodes optionnelles d'une interface avec des attributs</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("Le fichier n'existe pas.");
|
|
}
|
|
}
|
|
|
|
#[SetUp]
|
|
public function targetDirectoryExists()
|
|
{
|
|
if (!file_exists($this->targetDirectory)) {
|
|
mkdir($this->targetDirectory);
|
|
} elseif (!is_dir($this->targetDirectory)) {
|
|
throw new RuntimeException("Le répertoire cible $this->targetDirectory n'est pas un répertoire.");
|
|
}
|
|
}
|
|
|
|
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>Syntaxe des attributs</title>
|
|
|
|
<para>
|
|
La syntaxe des attributs consiste en plusieurs composants clés. Une déclaration d'attribut commence par <literal>#[</literal> et se termine par
|
|
<literal>]</literal>. À l'intérieur, un ou plusieurs attributs peuvent être listés, séparés par des virgules. Le nom de l'attribut peut être non qualifié, qualifié,
|
|
ou complètement qualifié, comme décrit dans <link linkend="language.namespaces.basics">Utilisation de base des espaces de noms</link>.
|
|
Les arguments de l'attribut sont optionnels et sont placés entre parenthèses <literal>()</literal>. Les arguments peuvent uniquement être des valeurs littérales ou des expressions constantes.
|
|
La syntaxe des arguments positionnels et nommés est supportée.
|
|
</para>
|
|
|
|
<para>
|
|
Les noms d'attributs et leurs arguments sont résolus vers une classe, et les arguments
|
|
sont passés à son constructeur lorsqu'une instance de l'attribut est demandée
|
|
via l'API de réflexion. Il est donc recommandé d'introduire une classe
|
|
pour chaque attribut.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Syntaxe des attributs</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>Lecture des attributs avec l'API de Reflection</title>
|
|
|
|
<para>
|
|
Pour accéder aux attributs des classes, méthodes, fonctions, paramètres, propriétés
|
|
et constantes de classe, il convient d'utiliser la méthode <function>getAttributes</function> fournie
|
|
par l'API de réflexion. Cette méthode retourne un tableau d'instances de <classname>ReflectionAttribute</classname>.
|
|
Ces instances permettent d'interroger le nom de l'attribut, ses arguments, et
|
|
peuvent être utilisées pour créer une instance de l'attribut représenté.
|
|
</para>
|
|
|
|
<para>
|
|
Séparer la représentation obtenue par réflexion d'un attribut de son instance réelle offre un meilleur
|
|
contrôle sur la gestion des erreurs, comme l'absence de classe d'attribut, les arguments
|
|
mal typés ou les valeurs manquantes. Les objets de la classe d'attribut ne sont instanciés
|
|
qu'après l'appel à <function>ReflectionAttribute::newInstance</function>, garantissant que
|
|
la validation des arguments a lieu à ce moment-là.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Lecture des attributs à l'aide de l'API de 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>
|
|
Plutôt que d'itérer sur tous les attributs d'une instance de réflexion,
|
|
il est possible de récupérer uniquement ceux d'une classe d'attribut spécifique
|
|
en passant le nom de la classe d'attribut en argument.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Lecture d'attributs spécifiques à l'aide de l'API de 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>Déclaration des classes d'attributs</title>
|
|
|
|
<para>
|
|
Il est recommandé de définir une classe distincte pour chaque attribut. Dans le cas le plus simple,
|
|
une classe vide avec la déclaration <literal>#[Attribute]</literal> est suffisante.
|
|
L'attribut peut être importé depuis le namespace global à l'aide d'une instruction <literal>use</literal>.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Classe d'attribut simple</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
namespace Example;
|
|
|
|
use Attribute;
|
|
|
|
#[Attribute]
|
|
class MyAttribute
|
|
{
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Pour restreindre les types de déclarations auxquels un attribut peut être appliqué,
|
|
passez un masque de bits en premier argument de la déclaration <literal>#[Attribute]</literal>.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Utilisation de la spécification de la cible pour restreindre l'utilisation des attributs</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
namespace Example;
|
|
|
|
use Attribute;
|
|
|
|
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
|
|
class MyAttribute
|
|
{
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
|
|
<para>
|
|
La déclaration de <classname>MyAttribute</classname> sur un autre type lèvera désormais une exception lors de
|
|
l'appel à <function>ReflectionAttribute::newInstance</function>
|
|
</para>
|
|
</example>
|
|
|
|
<para>Les cibles suivantes peuvent être spécifiées:</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>
|
|
Par défaut, un attribut ne peut être utilisé qu'une seule fois par déclaration.
|
|
Pour autoriser un attribut à être répété, il faut le spécifier dans le masque de bits
|
|
de la déclaration <literal>#[Attribute]</literal> en utilisant le drapeau
|
|
<constant>Attribute::IS_REPEATABLE</constant>.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Utilisation de IS_REPEATABLE pour permettre à un attribut d'être utilisé plusieurs fois dans une déclaration</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
|
|
-->
|