
在 PHP 中,类属性可以存储任何合法值,包括可调用对象(callable)——例如匿名函数、静态闭包、函数名字符串或数组形式的 [class, method]。但需特别注意:直接写 $this->handler() 会导致解析错误,因为 PHP 解析器会将其误判为方法调用而非属性值调用。正确做法是使用括号包裹属性访问表达式,强制将其作为可调用对象执行:
class Route
{
public callable $handler; // 推荐:PHP 8.0+ 支持 callable 类型声明
public function __construct(callable $handler)
{
$this->handler = $handler;
}
// 可选:封装调用逻辑,提升可读性与复用性
public function execute(): void
{
($this->handler)();
}
}✅ 正确调用方式(关键!):
// 方式1:直接调用(需括号)
$foo = fn() => echo "success";
$route = new Route($foo);
($route->handler)(); // 输出:success
// 方式2:使用函数名字符串(PHP 自动识别为 callable)
function bar(): void { echo "from bar"; }
$route2 = new Route('bar');
($route2->handler)(); // 输出:from bar
// 方式3:通过封装方法调用(更健壮)
$route->execute(); // 内部执行 ($this->handler)()⚠️ 注意事项:
- 括号不可省略:$obj->handler() 是非法语法;必须写作 ($obj->handler)() 或 call_user_func($obj->handler)。
- 类型安全优先:使用 callable 类型声明(PHP 7.0+)或属性类型(PHP 8.0+),避免运行时类型错误。
- 作用域敏感:若存储的是普通闭包(非 static fn),它会捕获定义时的作用域变量;静态闭包(static fn())则无此依赖,更适合跨上下文复用。
- 不推荐字符串函数名:如 new Route(‘foo’) 需确保 foo() 全局可见且未被重定义,易引发维护风险;优先使用闭包或 [$object, ‘method’] 形式。