找回密码
 立即注册
首页 业界区 业界 PHP 8.5 新特性 闭包可以作为常量表达式了 ...

PHP 8.5 新特性 闭包可以作为常量表达式了

栓汨渎 4 天前
PHP 8.5 新特性 闭包可以作为常量表达式了

PHP 8.5 又带来了一个让人兴奋的新特性:闭包现在可以作为常量表达式使用了,这意味着它们可以出现在默认参数或属性值中。
你是不是也遇到过这种情况:想在 PHP 中把闭包设置为默认参数值,结果只能想各种变通方案?在 PHP 8.5 中,这个烦恼终于没了。闭包现在可以作为常量表达式——也就是说,它们可以用在任何你之前只能用字面值的地方。
我之前就被这个限制坑过,而且不止一次。现在,你可以在这些地方使用闭包了:

  • 默认参数值
  • 常量值
  • 属性默认值
  • 属性参数值
  • 还有更多
PHP 8.5 新特性 闭包可以作为常量表达式了
默认值

以前,我会写这样的代码:
  1. function someFunction(mixed $someValue, ?callable $callback = null): bool
  2. {
  3.     $callback ??= fn () => true;
  4.     return $callback($someValue);
  5. }
复制代码
或者这样:
  1. final class SomeClass
  2. {
  3.     private Closure $someCallable;
  4.     public function __construct()
  5.     {
  6.         $this->someCallable = function (mixed $value): bool {
  7.             // 待实现
  8.             return true;
  9.         };
  10.     }
  11. }
复制代码
有了闭包常量表达式,这两个例子都可以简化成:
  1. function someFunction(
  2.     mixed $someValue,
  3.     callable $callback = static function () { return true; },
  4. ): bool {
  5.     return $callback($someValue);
  6. }
  7. final class SomeClass
  8. {
  9.     private Closure $someCallable = static function (mixed $value): bool {
  10.         // 待实现
  11.         return true;
  12.     };
  13. }
复制代码
不用再写 $callback ??= 这种绕来绕去的代码了。直接把闭包作为默认参数值是我经常要做的事,现在能够通过避免像 null 这种无意义的值来精简公共接口,这个改进真的很棒。
属性(Attributes)

这是另一个很赞的改变——你现在可以直接在属性中定义函数了。比如:
  1. #[Attribute(Attribute::TARGET_PROPERTY)]
  2. final readonly class TruthyValidator
  3. {
  4.     public function __construct(
  5.         public Closure $truthyValidator = static function(mixed $value): bool {
  6.             return (bool) $value;
  7.         }
  8.     ) {
  9.     }
  10. }
复制代码
这是一个简单的验证器属性,用来检查值是否为真值,默认实现就是把它转成布尔值,让 PHP 自己处理转换。但假如你想把字符串 '0' 也当作真值:
  1. #[TruthyValidator(truthyValidator: static function(string|int|null $value): bool {
  2.     return $value === '0' || $value;
  3. })]
  4. public string|int|null $someProperty = null;
复制代码
First-Class Callables

严格来说这是一个独立的 RFC,但它是因为投票原因才拆分的,技术上并不是独立的,所以我在同一篇文章里一起介绍。
除了标准的闭包(你可以内联定义函数体),现在你也可以用 first-class callables 作为常量表达式了。这意味着上面所有的例子也都适用于它们。
[code]

相关推荐

您需要登录后才可以回帖 登录 | 立即注册