Description
Description
The first-class callable syntax is currently not allowed in constant expressions:
class X {
const FN = strlen(...);
}
var_dump((X::FN)('test'));
// PHP Fatal error: Constant expression contains invalid operations
I propose partially supporting the first-class callable syntax in a constant expression. Specifically, I propose that PHP allows these two cases in a constant context:
class X {
const A = strlen(...);
const B = SomeClass::someStaticMethod(...);
}
While (still) disallowing expressions that cannot be known at compile time:
class X {
const C = $closure(...);
const D = $obj->method(...);
const E = ($obj->property)(...);
// etc. See the first-class callables RFC for a complete list
}
Example
Symfony's Choice
assertion allows the user to specify a callback. It would be nice if we could use the first-class callable syntax in attributes, but this is currently not allowed:
use Symfony\Component\Validator\Constraints as Assert;
class User {
#[Assert\Choice(callback: Role::values(...))] // Using this syntax here causes an error
public string $role;
}
enum Role: string
{
case Customer = 'customer';
case Admin = 'admin';
public static function values() {
return array_map(fn (Role $a) => $a->name, self::cases());
}
}
Implementation
I hacked together a working patch that supports the strlen(...)
syntax in constant expressions. I haven't gotten around to implementing SomeClass::someStaticFunction(...)
yet. There are probably some edge cases that I'm missing - I'm not too familiar with the PHP code base.
I'm also not sure if this feature would require an RFC. I would imagine it would, though.
Please let me know what you think.