Skip to content

Commit 0f14761

Browse files
committedMar 18, 2025·
Reworded parts of this section.
1 parent d5f735c commit 0f14761

File tree

1 file changed

+53
-58
lines changed

1 file changed

+53
-58
lines changed
 

‎language/attributes.xml

+53-58
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,26 @@
77
<?phpdoc print-version-for="attributes"?>
88

99
<para>
10-
Attributes offer the ability to add structured, machine-readable metadata information
11-
on declarations in code: Classes, methods, functions, parameters,
12-
properties and class constants can be the target of an attribute. The metadata
13-
defined by attributes can then be inspected at runtime using the
14-
<link linkend="book.reflection">Reflection
15-
APIs</link>. Attributes could therefore be thought of as a configuration
16-
language embedded directly into code.
10+
PHP attributes provide structured, machine-readable metadata for classes, methods,
11+
functions, parameters, properties, and constants. They can be inspected at runtime
12+
via the <link linkend="book.reflection">Reflection API</link>, enabling dynamic
13+
behavior without modifying code. Attributes provide a declarative way to annotate
14+
code with metadata.
1715
</para>
18-
1916
<para>
20-
With attributes the generic implementation of a
21-
feature and its concrete use in an application can be decoupled. In a way it is
22-
comparable to interfaces and their implementations. But where
23-
interfaces and implementations are about code, attributes are about
24-
annotating extra information and configuration. Interfaces can
25-
be implemented by classes, yet attributes can also be declared
26-
on methods, functions, parameters, properties and class constants.
27-
As such they are more flexible than interfaces.
17+
Attributes enable the decoupling of a feature's implementation from its usage. While
18+
interfaces define structure by enforcing methods, attributes provide metadata across multiple
19+
elements, including methods, functions, properties, and constants. Unlike interfaces,
20+
which enforce method implementations, attributes annotate code without altering its structure.
21+
</para>
22+
<para>
23+
Attributes can complement or replace optional interface methods by providing metadata instead of
24+
enforced structure. Consider an <literal>ActionHandler</literal> interface that represents an
25+
operation in an application. Some implementations may require a setup step while others do not.
26+
Instead of forcing all classes implementing <literal>ActionHandler</literal> to define a
27+
<literal>setUp()</literal> method, an attribute can indicate setup requirements. This approach
28+
increases flexibility, allowing attributes to be applied multiple times when necessary.
2829
</para>
29-
30-
<para>
31-
A simple example of attribute usage is to convert an interface
32-
that has optional methods to use attributes. Let's assume an
33-
<literal>ActionHandler</literal>
34-
interface representing an operation in an application, where some
35-
implementations of an action handler require setup and others do not. Instead of requiring all classes
36-
that implement <literal>ActionHandler</literal> to implement
37-
a method <literal>setUp()</literal>,
38-
an attribute can be used. One benefit
39-
of this approach is that we can use the attribute several times.
40-
</para>
4130

4231
<example>
4332
<title>Implementing optional methods of an interface with Attributes</title>
@@ -112,21 +101,21 @@ executeAction($copyAction);
112101
<title>Attribute syntax</title>
113102

114103
<para>
115-
There are several parts to the attributes syntax. First, an attribute
116-
declaration is always enclosed with a starting
117-
<literal>#[</literal> and a corresponding ending
118-
<literal>]</literal>. Inside, one or many attributes are listed,
119-
separated by comma. The attribute name is an unqualified, qualified
120-
or fully-qualified name as described in <link linkend="language.namespaces.basics">Using Namespaces Basics</link>.
121-
Arguments to the attribute are optional, but are enclosed in the usual parenthesis <literal>()</literal>.
122-
Arguments to attributes can only be literal values or constant expressions. Both positional and
123-
named arguments syntax can be used.
104+
Attribute syntax consists of several key components. An attribute
105+
declaration starts with <literal>#[</literal> and ends with
106+
<literal>]</literal>. Inside, one or more attributes can be listed,
107+
separated by commas. The attribute name can be unqualified, qualified,
108+
or fully-qualified, as described in <link linkend="language.namespaces.basics">Using Namespaces Basics</link>.
109+
Arguments to the attribute are optional and enclosed in parentheses
110+
<literal>()</literal>. Arguments can only be literal values or constant
111+
expressions. Both positional and named argument syntax are supported.
124112
</para>
125113

126114
<para>
127-
Attribute names and their arguments are resolved to a class and the arguments are passed to its constructor,
128-
when an instance of the attribute is requested through the Reflection API. As such
129-
a class should be introduced for each attribute.
115+
Attribute names and their arguments are resolved to a class, and the arguments
116+
are passed to its constructor when an instance of the attribute is requested
117+
through the Reflection API. Therefore, it is recommended to introduce a class
118+
for each attribute.
130119
</para>
131120

132121
<example>
@@ -184,17 +173,19 @@ class AnotherThing
184173
<title>Reading Attributes with the Reflection API</title>
185174

186175
<para>
187-
To access attributes from classes, methods, functions, parameters, properties and class constants,
188-
the Reflection API provides the method <function>getAttributes</function> on each of the corresponding
189-
Reflection objects. This method returns an array of <classname>ReflectionAttribute</classname> instances
190-
that can be queried for attribute name, arguments and to instantiate an instance of the represented attribute.
176+
To access attributes from classes, methods, functions, parameters, properties,
177+
and class constants, use the <function>getAttributes</function> method provided
178+
by the Reflection API. This method returns an array of <classname>ReflectionAttribute</classname>
179+
instances. These instances can be queried for the attribute name, arguments, and
180+
can be used to instantiate an instance of the represented attribute.
191181
</para>
192182

193183
<para>
194-
This separation of reflected attribute representation from actual instance increases control of the programmer
195-
to handle errors regarding missing attribute classes, mistyped or missing arguments. Only after
196-
calling <function>ReflectionAttribute::newInstance</function>, objects of the attribute class are instantiated and the correct matching of arguments
197-
is validated, not earlier.
184+
Separating the reflected attribute representation from its actual instance provides more
185+
control over error handling, such as missing attribute classes, mistyped arguments,
186+
or missing values. Objects of the attribute class are instantiated only after calling
187+
<function>ReflectionAttribute::newInstance</function>, ensuring that argument validation
188+
occurs at that point.
198189
</para>
199190

200191
<example>
@@ -248,9 +239,9 @@ object(MyAttribute)#3 (1) {
248239
</example>
249240

250241
<para>
251-
Instead of iterating all attributes on the reflection instance, only those
252-
of a particular attribute class can be
253-
retrieved by passing the searched attribute class name as argument.
242+
Instead of iterating over all attributes on the reflection instance,
243+
you can retrieve only those of a specific attribute class by passing
244+
the attribute class name as an argument.
254245
</para>
255246

256247
<example>
@@ -280,9 +271,10 @@ dumpMyAttributeData(new ReflectionClass(Thing::class));
280271
<title>Declaring Attribute Classes</title>
281272

282273
<para>
283-
While not strictly required it is recommended to create an actual class for every attribute.
284-
In the most simple case only an empty class is needed with the <literal>#[Attribute]</literal> attribute declared
285-
that can be imported from the global namespace with a use statement.
274+
It is recommended to define a separate class for each attribute. In the simplest
275+
case, an empty class with the <literal>#[Attribute]</literal> declaration is sufficient.
276+
The attribute can be imported from the global namespace using a <literal>use</literal>
277+
statement.
286278
</para>
287279

288280
<example>
@@ -305,8 +297,9 @@ class MyAttribute
305297
</example>
306298

307299
<para>
308-
To restrict the type of declaration an attribute can be assigned to, a bitmask can be passed as the first
309-
argument to the <literal>#[Attribute]</literal> declaration.
300+
To restrict the types of declarations an attribute can be applied to,
301+
pass a bitmask as the first argument to the <literal>#[Attribute]</literal>
302+
declaration.
310303
</para>
311304

312305
<example>
@@ -346,8 +339,10 @@ class MyAttribute
346339
</simplelist>
347340

348341
<para>
349-
By default an attribute can only be used once per declaration. If the attribute should be repeatable on declarations it must
350-
be specified as part of the bitmask to the <literal>#[Attribute]</literal> declaration.
342+
By default, an attribute can only be used once per declaration. To allow
343+
an attribute to be repeatable, specify it in the bitmask of the
344+
<literal>#[Attribute]</literal> declaration using the
345+
<constant>Attribute::IS_REPEATABLE</constant> flag.
351346
</para>
352347

353348
<example>

0 commit comments

Comments
 (0)
Please sign in to comment.