MENU
Attributes
Since PHP 8.0, attributes attach structured, machine-readable metadata directly to a class, method, property, parameter, or function using #[...] syntax. Unlike the doc-comment annotations frameworks used to parse by hand, attributes are part of the language itself and can be read back at runtime through Reflection.A class marked #[\Attribute] becomes usable as an attribute on other declarations. getAttributes() retrieves the ones applied to a given class, method, or property, and newInstance() builds the real object from the arguments written inside #[...].
Beyond custom attributes, PHP itself now recognizes several attributes natively – the engine acts on them directly, with no Reflection code of your own required. Here is a brief look at four of them.
PHP 8.4's #[\Deprecated] marks a function or method as deprecated. Every call to it emits a real E_DEPRECATED notice automatically, including an optional custom message and version, without needing an explicit trigger_error() call:
<?php
declare(strict_types=1);
#[\Attribute]
class Route {
public function __construct(public string $path, public string $method = "GET") {}
}
#[Route("/users", method: "POST")]
class UserController {
#[Route("/users/{id}")]
public function show(int $id) {}
#[Route("/users/{id}/name")]
public string $displayName = "";
}
$classReflection = new ReflectionClass(UserController::class);
foreach ($classReflection->getAttributes(Route::class) as $attribute) {
$route = $attribute->newInstance();
echo "Class route: {$route->path} [{$route->method}]\n";
}
$methodReflection = $classReflection->getMethod('show');
foreach ($methodReflection->getAttributes(Route::class) as $attribute) {
$route = $attribute->newInstance();
echo "Method route: {$route->path} [{$route->method}]\n";
}
$propertyReflection = $classReflection->getProperty('displayName');
foreach ($propertyReflection->getAttributes(Route::class) as $attribute) {
$route = $attribute->newInstance();
echo "Property route: {$route->path} [{$route->method}]\n";
}
?>Class route: /users [POST]
Method route: /users/{id} [GET]
Property route: /users/{id}/name [GET]
<?php
class Calculator {
#[\Deprecated(message: "use add() instead", since: "8.4")]
public function sum($a, $b) {
return $a + $b;
}
public function add($a, $b) {
return $a + $b;
}
}
$calc = new Calculator();
echo $calc->sum(2, 3) . "\n";
echo $calc->add(2, 3) . "\n";
?>Deprecated: Method Calculator::sum() is deprecated since 8.4, use add() instead in D:\xampp\htdocs\attributes-deprecated.php on line 14
5
5
<?php
class Base {
public function greet(): string {
return "Hi";
}
}
class Child extends Base {
#[\Override]
public function greet(): string {
return "Hello";
}
}
$c = new Child();
echo $c->greet() . "\n";
?>Hello
<?php
function login(string $username, #[\SensitiveParameter] string $password) {
throw new \RuntimeException("Login failed");
}
try {
login("alice", "secret123");
} catch (\RuntimeException $e) {
echo $e->getTraceAsString() . "\n";
}
?>#0 D:\xampp\htdocs\attributes-sensitive-parameter.php(7): login('alice', Object(SensitiveParameterValue))
#1 {main}
<?php
#[\NoDiscard]
function computeChecksum(string $data): string {
return md5($data);
}
computeChecksum("hello");
$sum = computeChecksum("hello");
echo $sum . "\n";
?>Warning: The return value of function computeChecksum() should either be used or intentionally ignored by casting it as (void) in D:\xampp\htdocs\attributes-nodiscard.php on line 7
5d41402abc4b2a76b9719d911017c592