在 php 8 中,先用 #[attribute] 声明一个属性类,再用 #[类名(参数)] 标记目标类。运行时通过 reflectionclass::getattributes() 查找标记,通过 newinstance() 读取构造参数。
声明一个只允许标记类的属性
把下面代码保存为 attributes-demo.php。ReportExport 属性用于记录报表的名称和格式。
<?php
declare(strict_types=1);
#[Attribute(Attribute::TARGET_CLASS)]
final class ReportExport
{
public function __construct(
public string $label,
public string $format = 'csv',
) {}
}
#[ReportExport('库存盘点', format: 'xlsx')]
final class InventoryReport {}
属性参数会被传给 ReportExport 的构造函数。标记本身不会自动生成或导出文件。
通过反射读取标记参数
把下面的代码追加到同一脚本。按属性类型过滤,再实例化查到的第一项。
立即学习“PHP免费学习笔记(深入)”;
function readReportExport(string $class): ?ReportExport
{
$reflection = new ReflectionClass($class);
$attributes = $reflection->getAttributes(ReportExport::class);
return $attributes === [] ? null : $attributes[0]->newInstance();
}
$export = readReportExport(InventoryReport::class);
if ($export !== null) {
printf("%s | %s\n", $export->label, $export->format);
}
执行 php attributes-demo.php,预期输出「库存盘点 | xlsx」。如果只需要原始参数,可以读取 ReflectionAttribute 的 getArguments()。
验证没有标记的类
用普通类验证查不到属性时的分支。
final class PlainReport {}
var_dump(readReportExport(PlainReport::class));预期输出 NULL。属性目标不合法或构造参数不匹配时,实例化可能报错,应修正声明和调用。



















