On Fri, Apr 5, 2024, at 2:20 PM, Joel Wurtz wrote:
>> Would it make sense to not only add this for ReflectionAttribute, but also
>> Function and/or others?
>
> There may be case where this makes sense but not necessarily in the use
> case that i explain, and don't want to add more to this proposal, it's
> also missing in ReflectionParameter, ReflectionProperty and certainly
> many others if we go on this path then there is a lot of changes to
> apply and will induce more friction for this proposal, i prefer to add
> small parts so we don't deviate from the original use case.
>
>> Do you have an example of how you expect this to be used? I'm having a hard
>> time understanding how I'd leverage this. (I maintain an attribute
>> enhancement library, Crell/AttributeUtils, so I've hit a lot of edge cases
>> in attribute design.)
>
> Sure, let's say we have the following class
>
> #[CustomAttribute(foo: 'foo')
> #[CustomAttribute(foo: 'foo')
> class Entity {}
>
> And that later i have something that read those attributes, but i want
> to throw an Exception when multiple attribute defined the same value
> for the foo property (as it should be unique in my use case), i would
> not be able to do that in the constructor since i don't have the
> context of others attributes in this case, so i want to throw a custom
> exception explaining it's caused by the attribute "CustomAttribute" in
> the file "Entity.php" at line 4, as there is the same value in the file
> "Entity.php" at line 3
>
> If I throw an exception without this message the error will pinpoint to
> where I threw the exception and it may be confusing for the end user,
> by having this he will know where to look and what to modify to make
> its code correct.
OK, so the idea is you could do something like:
$rClass = new ReflectionClass(Entity::class);
$as = $rClass->getAttributes();
$attribs = array_map(fn(ReflectionAttribute $r) => $r->getInstance(), $as);
$values = array_map(fn(CustomAttribute $r) => $r->foo, $attribs);
if ($values is not unique) {
$msg = sprintf('You have too many %s on in file %s on line %d',
Entity::class, $as[0]->getFile(), $as[0]->getLine());
throw new Exception($msg);
}
(Or something like that.)
That works, I suppose, but couldn't that also be done with
ReflectionClass::getStartLine() and ReflectionClass::getFileName()?
--Larry Garfield