Thanks for the feedback! On Tue, 30 May 2023 at 03:43, Dusk <d...@woofle.net> wrote: > > On May 29, 2023, at 17:48, Andreas Hennings <andr...@dqxtech.net> wrote: > > Quite often I found myself writing attribute classes that need to fill > > some default values or do some validation based on the symbol the > > attribute is attached to. > > E.g. a parameter attribute might require a specific type on that > > parameter, or it might fill a default value based on the parameter > > name. > > +1. This is a substantial limitation in the attribute system. > > > Currently I see two ways to do this: > > 1. Do the logic in the code that reads the attribute, instead of the > > attribute class. This works ok for one-off attribute classes, but it > > becomes quite unflexible with attribute interfaces, where 3rd parties > > can provide their own attribute class implementations. > > 2. Add additional methods to the attribute class that take the symbol > > reflector as a parameter, like "setReflectionMethod()", or > > "setReflectionClass()". Or the method in the attribute class that > > returns the values can have a reflector as a parameter. > > I see a third way which introduces less "magic":
Actually, these two options are what is possible with the current version of PHP, but it requires to write php code to solve these problems each time. The actual proposal in terms of "language design" solution was further below in my email :) > > 3.a. Add a method to ReflectionAttribute which retrieves the target of the > attribute as an appropriate reflection object. (Sadly, the obvious name > "getTarget" is already taken; I'll call it "getReflectionTarget" for now.) > > 3.b. Add a static method to ReflectionAttribute which, when called within an > Attribute constructor which is being called by > ReflectionAttribute::newInstance(), returns the ReflectionAttribute object > which is being instantiated. > > These features could be used together to set a default property on an > attribute based on its target, e.g. > > #[Attribute(Attribute::TARGET_PROPERTY)] > class PropertyAnnotation { > public string $name; > > public function __construct(?string $name = null) { > $this->name = $name ?? > ReflectionAttribute::underConstruction()->getReflectionTarget()->getName(); > } > } > > Another variant that comes to mind is: > > 3.b. Add a new flag to attributes which causes the ReflectionAttribute object > to be passed to the constructor as the first argument, e.g. > > #[Attribute(Attribute::TARGET_PROPERTY | Attribute::WHO_MADE_ME)] > class PropertyAnnotation { > public string $name; > > public function __construct(ReflectionAttribute $attr, ?string $name = > null) { > $this->name = $name ?? $attr->getReflectionTarget()->getName(); > } > } > > This is a little messier because it can't be used "under the covers" by an > attribute base class, but it accomplishes the same goals. This is close to the parameter attribute I proposed. The benefit of the parameter attribute is that a developer can clearly see which parameter will be skipped for regular arguments. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php