Larry Garfield <[email protected]>: > On Sun, May 17, 2026, at 9:05 AM, Valentin Udaltsov wrote: > > Daniel Scherzer <[email protected]>: > >> Hi internals, > >> > >> I'd like to start the discussion for a new RFC about adding a new > method, ReflectionAttribute::getCurrent(), to access the current reflection > target of an attribute. > >> > >> * RFC: https://wiki.php.net/rfc/reflectionattribute-getcurrent > >> * Implementation: https://github.com/php/php-src/pull/21440 > >> > >> Thanks, > >> -Daniel > > > > Hi, Daniel! > > > > Thank you for your proposal. > > > > I think the problem you are trying to solve arises from mixing two > > responsibilities in a single attribute class — it acts both as a data > > container and as a place for resolution logic. Separating these > > concerns makes the code cleaner and removes the need to access the > > reflection target from within the attribute itself. > > > > In my opinion, an attribute should be a simple DTO, and the resolution > > logic should belong elsewhere. Here's a small example of that: > > https://gist.github.com/vudaltsov/6dbab6a69967a55037fc7d6b13bd593b Here > > the messageClass can be inferred either from the attribute or from the > > function signature — the Metadata class has a non-nullable > > messageClass, and the attribute remains a plain DTO with an optional > > parameter. Of course, you can add a MetadataDriver interface and move > > my static methods to implementations, this will work especially well if > > you have multiple configuration sources (YAML, XML, attributes, PHP > > DSL, etc.). > > > > So, I believe that attributes should not be aware of the context they > > are declared in because the resolution responsibility does not belong > > to them. > > > > -- > > Valentin > > What you're saying implies that in the Serde examples I showed, you'd need > *three* classes instead of one. > > 1. An attribute with the basic data. > 2. A resolver object that uses data in the attribute and the reflection > target to build some new value object. > 3. The resulting value object. > > Which means that all three need different names, too. That is, quite > frankly, grotesquely over-engineered (and I say that as someone with a > penchant for over-engineering things) and highly confusing. Trying to set > that up for a new use case is then substantially more work than it needs to > be. > > --Larry Garfield >
I gave an example with only two classes, because I don't like over-engineering either :) I think placing resolution logic in a static constructor of the resulting class is perfectly fine. Anyway, when you mix responsibilities to make code simpler, you should expect some trade-offs — that's OK. But I don't think the language should compensate for that, especially with a hack like this. There's another concern with the proposed approach: testing. Currently I don't need to test my attributes — they are simple structs. But with this RFC, logic can move into the primary constructor, and that logic needs unit tests. The only feasible way to test it is to place an attribute on a target and reflect it — which feels cumbersome to me. -- Valentin
