# RFC: Attribute Amendments

- Status: Implemented (PHP 8.0)
- Authors: Benjamin Eberlei (beberlei@php.net), Martin Schröder
- Date: 2020-05-11
- Version: 1.2
- Target: 8.0
- Original: https://wiki.php.net/rfc/attribute_amendments
- Page: https://externals.io/rfc/attribute_amendments
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Should PhpAttribute be renamed to Attribute? (closed)

Yes: 51 · No: 0

Voters: alcaeus (Yes), alec (Yes), asgrim (Yes), ashnazg (Yes), beberlei (Yes), bmajdak (Yes), brzuchal (Yes), bwoebi (Yes), carusogabriel (Yes), colinodell (Yes), cpriest (Yes), danack (Yes), daverandom (Yes), derick (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jasny (Yes), jbnahan (Yes), jhdxr (Yes), kalle (Yes), kelunik (Yes), kguest (Yes), klaussilveira (Yes), kocsismate (Yes), marandall (Yes), marcio (Yes), mariano (Yes), mbeccati (Yes), mike (Yes), nicolasgrekas (Yes), nikic (Yes), ocramius (Yes), patrickallaert (Yes), pierrick (Yes), pmjones (Yes), pollita (Yes), ramsey (Yes), reywob (Yes), ruudboon (Yes), santiagolizardo (Yes), sebastian (Yes), sergey (Yes), sirsnyder (Yes), stas (Yes), svpernova09 (Yes), tandre (Yes), thekid (Yes), theodorejb (Yes), trowski (Yes), zimt (Yes)

### Should a secondary grouped syntax for attributes be introduced? (closed)

Yes: 32 · No: 14

Voters: alcaeus (Yes), alec (No), asgrim (Yes), ashnazg (Yes), beberlei (Yes), bmajdak (Yes), brzuchal (Yes), bwoebi (Yes), cpriest (Yes), danack (No), daverandom (Yes), derick (No), galvao (Yes), heiglandreas (No), jasny (No), jbnahan (Yes), jhdxr (No), kalle (Yes), kelunik (Yes), kguest (Yes), klaussilveira (Yes), kocsismate (No), marandall (Yes), marcio (Yes), mariano (Yes), mbeccati (Yes), mike (Yes), nicolasgrekas (Yes), ocramius (Yes), patrickallaert (No), pierrick (Yes), pollita (Yes), ramsey (Yes), rasmus (No), reywob (No), ruudboon (Yes), santiagolizardo (Yes), sebastian (No), sergey (Yes), sirsnyder (Yes), stas (No), svpernova09 (Yes), thekid (Yes), theodorejb (No), trowski (Yes), zimt (No)

### Should attributes allow definition of target declarations? (closed)

Yes: 38 · No: 4

Voters: alcaeus (Yes), alec (Yes), asgrim (Yes), ashnazg (Yes), beberlei (Yes), bmajdak (Yes), brzuchal (Yes), bwoebi (Yes), colinodell (Yes), cpriest (No), danack (No), daverandom (Yes), derick (Yes), galvao (Yes), jasny (Yes), jbnahan (Yes), jhdxr (Yes), kalle (Yes), kelunik (Yes), kguest (Yes), klaussilveira (Yes), kocsismate (Yes), marandall (Yes), marcio (Yes), mariano (Yes), mbeccati (Yes), mike (Yes), nicolasgrekas (Yes), ocramius (Yes), pierrick (Yes), pollita (Yes), ramsey (Yes), rasmus (No), reywob (Yes), ruudboon (Yes), sebastian (Yes), sergey (Yes), sirsnyder (Yes), stas (No), svpernova09 (Yes), tandre (Yes), trowski (Yes)

### Should attributes allow definition of repeatability? (closed)

Yes: 38 · No: 4

Voters: alcaeus (No), alec (Yes), asgrim (Yes), ashnazg (Yes), beberlei (Yes), bmajdak (Yes), brzuchal (Yes), bwoebi (Yes), cpriest (Yes), danack (No), daverandom (Yes), derick (Yes), galvao (Yes), jasny (No), jbnahan (Yes), jhdxr (Yes), kalle (Yes), kelunik (Yes), kguest (Yes), klaussilveira (Yes), kocsismate (Yes), marandall (Yes), marcio (Yes), mariano (Yes), mbeccati (Yes), mike (Yes), nicolasgrekas (Yes), ocramius (Yes), patrickallaert (Yes), pierrick (Yes), pollita (Yes), ramsey (Yes), reywob (Yes), ruudboon (Yes), santiagolizardo (Yes), sebastian (Yes), sergey (Yes), sirsnyder (Yes), stas (No), svpernova09 (Yes), tandre (Yes), trowski (Yes)

## Discussions on the mailing list

- [\[RFC\] Amendments to Attributes](https://externals.io/message/110217.md) — started on 2020-05-20, 30 messages
- [\[VOTE\] Attribute Amendments](https://externals.io/message/110416.md) — started on 2020-06-08, 14 messages
- [Typed constants](https://externals.io/message/110755.md) — started on 2020-06-28, 3 messages

---

## Introduction

This RFC discusses a few amendments to the [original Attributes RFC](https://externals.io/rfc/attributes_v2) that was accepted for PHP 8.

## Rename PhpAttribute class to Attribute

Important Context: Since the acceptence of Attributes, the PhpCompilerAttribute and PhpAttribute classes were unified to be only PhpAttribute. This was needed because the previous approach of disallowing the use of &lt;&lt;PhpCompilerAttribute&gt;&gt; in userland would break "stub" generation that static analysis and IDEs rely on to fill their type database of internal functions/classes. Without it there was no functionality left in PhpCompilerAttribute to preserve.

The original RFC introduced a *PhpAttribute* class to be added to new userland attributes. This name was inspired by *PhpToken* and to potentially avoid breaking existing userland codebases with a class called *Attribute*. However the *Php* prefix makes no sense for the attribute class compared to *PhpToken*.

In absence of a namespace policy, the global namespace is PHPs namespace. The documentation states as much and the vote on <https://externals.io/rfc/php-namespace-in-core> confirmed this.

Therefore we propose to rename *PhpAttribute* to be just *Attribute* and in addition recommend that all internal/compiler attributes should be placed under the global namespace as well.

Extensions providing non-core attributes should consider using their own namespace, but this RFC makes no recommendation or rule about this.

## Group statement for Attributes

Right now each attribute requires to be surrounded by the T\_SL/T\_SR tokens:

```php
<<Attr1>><<Attr2>>
class Example
{
    <<Attr2("foo")>>
    <<Attr2("bar")>>
    public function test()
    {
    }
}
```

We propose to allow a second syntax/style to group attributes in one declaration:

```php
<<Attr1, Attr2>>
class Example
{
    <<Attr2("foo"),
      Attr2("bar")>>
    public function test()
    {
    }
}
```

In line with many other recent RFCs, trailing commas will also be possible in an attribute group declarations:

```php
    <<
      Attr1("foo"),
      Attr2("bar"),
    >>
    public function test()
    {
    }
```

This feature would be superseded by any other RFC getting accepted that changes the syntax.

## Validate Attribute Target Declarations

At the moment an attribute can be put on any kind of declaration and the developer of the attribute has no way of restricting the usage to only a subset of declarations. This functionality is only available to internal attributes for now.

As an example, a developer might introduce an attribute to declare what database table a class is stored in:

```php
use ORM\Attributes\Table;
 
<<Table("users")>>
class User
{
}
```

But they cannot prevent the Table attribute being used on another declaration where it semantically does not belong:

```php
use ORM\Attributes\Table;
 
class User
{
    <<Table("users")>>
    public $id;
}
```

We propose that you can optionally restrict the declarations an attribute can be used on by setting an optional argument to *PhpAttribute* (or *Attribute*).

```php
namespace ORM\Attributes;
 
<<PhpAttribute(PhpAttribute::TARGET_CLASS)>>
class Table
{
}
```

The following constants will be added to *PhpAttribute*:

```php
class PhpAttribute
{
    public const int TARGET_CLASS = 1;
    public const int TARGET_FUNCTION = (1 << 1);
    public const int TARGET_METHOD = (1 << 2);
    public const int TARGET_PROPERTY = (1 << 3);
    public const int TARGET_CLASS_CONSTANT = (1 << 4);
    public const int TARGET_PARAMETER = (1 << 5);
    public const int TARGET_ALL = ((1 << 6) - 1);
 
    public function __construct(int $flags = self::TARGET_ALL)
    {
    }
}
```

Important note: The target definition of an attribute is validated during the call to *ReflectionAttribute::newInstance*. In fact it does not influence a call to *Reflection\*::getAttributes()* and *ReflectionAttribute* instances can be returned from this method, that are not valid on the reflected declaration. This is in line with the deferred validation of userland attributes that the original RFC championed.

## Validate Attribute Repeatability

At the moment every attribute can be repeated multiple times on a declaration. For many use cases of attributes this is not desired.

For this reason we propose that by default attributes are not repeatable, and only if the *PhpAttribute* has the flag *IS\_REPEATABLE*should it be possible to use it multiple times on the same declaration:

```php
class PhpAttribute
{
    public const int IS_REPEATABLE = ((1 << 10));
}
 
<<PhpAttribute(self::IS_REPEATABLE)>>
class Route
{
}
 
class HomepageController
{
    <<Route("/")>>
    <<Route("/homepage")>>
    public function indexAction()
    {
    }
}
```

Important note: The repeatable flag of an attribute is validated during the call to *ReflectionAttribute::newInstance*. In fact it does not influence a call to *Reflection\*::getAttributes()* and *ReflectionAttribute* instances can be returned from this method, that are not valid on the reflected declaration. This is in line with the deferred validation of userland attributes that the original RFC championed.

## Backward Incompatible Changes

Introducing a class *Attribute* into the global namespace is certainly going to break at least a handful of applications using this class name.

## Proposed PHP Version(s)

8.0

## RFC Impact

### To SAPIs

none

### To Existing Extensions

none

### To Opcache

none

## Open Issues

none

## Vote

Voting will end on June 22nd, 2020 - 8:00 UTC.

### Rename PhpAttribute class to Attribute

**Vote: Should PhpAttribute be renamed to Attribute?** — Yes: 51 · No: 0 (closed)

### Group statement for Attributes

**Vote: Should a secondary grouped syntax for attributes be introduced?** — Yes: 32 · No: 14 (closed)

### Validate Attribute Target Declarations

**Vote: Should attributes allow definition of target declarations?** — Yes: 38 · No: 4 (closed)

### Validate Attribute Repeatability

**Vote: Should attributes allow definition of repeatability?** — Yes: 38 · No: 4 (closed)

## Patches and Tests

1. <https://github.com/php/php-src/pull/5751>

## References

1. [Attributes RFC](https://externals.io/rfc/attributes_v2)

## Updates

1. 1.0 Initial RFC (11.5.2020)
2. 1.1 Attributes\\Attribute namespace (28.5.2020)
3. 1.2 Revert Attributes\\Attribute namespace, make IS\_REPEATABLE flag on PhpAttribute (4.6.2020)
