I have a project that use attributes :
#[OperationQueryParam('id', IntegerOperation::class, requirements: new Numeric(min: 1, max: 2_147_483_647))]
Everything works fine but there are multiple attribute that have the same requirement argument new Numeric(min: 1, max: 2_147_483_647)
so i wanted to create a static function in my numeric class :
final public static function createPostiveInt(): self {
return new self(min:1, max:2_147_483_647);
}
then call the static function instead of the direct instanciation of the Numeric object to avoid repeating the constructor parameters.
#[OperationQueryParam('id', IntegerOperation::class, requirements: Numeric::createPostiveInt())]
but i have this error : Compile Error: Constant expression contains invalid operations
Am i missing something ? Why does a direct instanciation works but not the static function ?
EDIT :
using define(POSITIVE_INT,Numeric::createPostiveInt());
works but it seems dirty.
2
Answers
Depending on how the project uses reflection to get attribute values, it might be possible for you to subclass
OperationQueryParam
and include your constant values viaparent::__construct()
. To do this, the reflecting code must not check for simple equality on class name, but check for it being an instance of it. There’s a couple of ways to do this, but one option is to use the secondparameter to
getAttributes()
which isReflectionAttribute::IS_INSTANCEOF
Below is a quick PoC. We have a base attribute which requires a
$name
parameter, and then our custom attribute which doesn’t, and instead includes that in the parent constructor.Demo: https://3v4l.org/SWTa6#v8.3.8
If the project is a third-party and you can’t modify things, it might be worth it kicking this request upstream to see if they are willing to modify it.
From https://www.php.net/manual/en/functions.arguments.php:
In other words, you can’t use a run-time construct like a function call as a default value for a parameter. You could extend the Numeric class here, to build-in your common defaults:
Or even just remove the args completely:
And then your definition becomes: