On Thu, Jul 3, 2025, at 12:49 PM, Andreas Hennings wrote: >> A setter method injection is what I did in AttributeUtils, because it was >> the only real option. > > In my experience, this alternative leads to more complexity in > attribute classes. > The constructor needs to populate the attribute with temporary values, > which are then replaced in that separate method. > (I call that a "setter", but only because it behaves like one from the > outside, internally we usually don't want to store the reflector). > > Also, we can never be fully sure whether an attribute instance is > "complete" or not. > If the attribute instance is coming from > $reflection_attribute->newInstance(), we can be confident that the > ->injectReflector() or has been called. > But if the attribute was instantiated manually with "new ...", it > could as well be incomplete. > With ReflectionAttribute::getCurrentTargetReflector(), we can fail > early in the attribute constructor, by throwing on NULL.
I ran into the "completeness problem" in AttributeUtils as well. In my case, it's not just reflection; there's a whole bunch of other things that can be passed back to the attribute to give it more context. My eventual solution was to also have a `Finalizable` interface that is guaranteed to be the last thing called, so the attribute can handle any last-minute defaults. I don't love it, but given the severe limitations of `readonly` it was the best I could do. (With aviz today, I could likely do better.) Basically, any time you have multi-step construction you will have a period where the state is potentially incomplete. While passing the reflection target in is one such multi-step case, there are lots of others, so in advanced cases (most of what I do) the object will always have an incomplete phase, and that's unavoidable. So I'm not *that* worried about there being a brief incomplete-gap in time in core, because I'll always have one anyway, and I've already figured out how to handle it. --Larry Garfield