PHP Velho Oeste 2024

Attribute syntax

There are several parts to the attributes syntax. First, attribute declaration are always enclosed with a starting #[ and a corresponding ending ]. Inside, one or many attributes are listed, seperated by comma. The attribute name is an unqualified, qualified or fully-qualified name as described in Using Namespaces Basics. Arguments to the attribute are optional, but are enclosed in the usual parenthesis (). Arguments to attributes can only be literal values or constant expressions. Both positional and named arguments syntax can be used.

Attribute names and their arguments are resolved to a class and the arguments are passed to its constructor, when an instance of the attribute is requested through the Reflection API. As such a class should be introduced for each attribute.

Example #1 Attribute Syntax

<?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
{
}
add a note add a note

User Contributed Notes 1 note

up
1
yarns dot purport0n at icloud dot com
4 months ago
It wasn't obvious to me for a while but you can subclass attributes

https://3v4l.org/TrMTe

<?php

#[Attribute(Attribute::TARGET_PROPERTY)]
class PropertyAttributes
{
    public function
__construct(
        public
readonly ?string $name = null,
        public
readonly ?string $label = null,
    ) {}
}

#[Attribute(Attribute::TARGET_PROPERTY)]
class IntegerPropertyAttributes extends PropertyAttributes
{
    public function
__construct(
        ?
string $name = null,
        ?
string $label = null,
        public
readonly ?int $default = null,
        public
readonly ?int $min = null,
        public
readonly ?int $max = null,
        public
readonly ?int $step = null,
    ) {
       
parent::__construct($name, $label);
    }
}

#[Attribute(Attribute::TARGET_PROPERTY)]
class FloatPropertyAttributes extends PropertyAttributes
{
    public function
__construct(
        ?
string $name = null,
        ?
string $label = null,
        public
readonly ?float $default = null,
        public
readonly ?float $min = null,
        public
readonly ?float $max = null,
    ) {
       
parent::__construct($name, $label);
    }
}

class
MyClass
{
    
#[IntegerPropertyAttributes('prop', 'property: ', 5, 0, 10, 1)]
    
public int $prop;
}

$refl = new ReflectionProperty('MyClass', 'prop');
$attributes = $refl->getAttributes();

    foreach (
$attributes as $attribute) {
      
var_dump($attribute->getName());
      
var_dump($attribute->getArguments());
      
var_dump($attribute->newInstance());
    }
?>
To Top