On Thu, Jul 3, 2025, at 12:54 PM, Andreas Hennings wrote:
>> > A setter method injection is what I did in AttributeUtils, because it was
>> > the only real option. Alternatively, I suppose core could use property
>> > setter injection (either a magically named property like $__reflector, or
>> > a property that itself has an attribute on it, etc.). That would allow it
>> > to be set before the constructor is called, and with property hooks would
>> > allow processing either immediately or later in the constructor. The
>> > downside here is that Attribute are, generally, serializable, but a
>> > Reflection object is not. So if someone wanted a serializable attribute
>> > they would have to accept the property, use it, and then remember to unset
>> > it at some point. That's clumsy.
>> >
>> > --Larry Garfield
>> >
>>
>> As someone that's written yet another userland "solution" for this problem,
>> I have an alternative solution, based somewhat on an internalised concept
>> of "never store Reflectors".
>>
>> Introduce an interface "ReflectorAttribute" (bike shedding to come); which
>> accepts a single Reflector argument.
>>
>> If the attribute implements the interface, the method is called immediately
>> following instantiation.
>
> Yep, this is the "method injection" mentioned by Larry, or what I
> referred to as "setter injection".
> I have not seen your library, but I assume that's where it is going.
Yes, that is what AttributeUtils does today, almost exactly. From the docs:
#[\Attribute]
class AttribWithName implements FromReflectionClass
{
public readonly string $name;
public function __construct(?string $name = null)
{
if ($name) {
$this->name = $name;
}
}
public function fromReflection(\ReflectionClass $subject): void
{
$this->name ??= $subject->getShortName();
}
}
(There's a different interface for each type of thing an attribute can be put
on because the parameter type is different.)
--Larry Garfield