On Fri, Oct 30, 2020 at 2:28 PM Rowan Tommins <rowan.coll...@gmail.com> wrote:

> On 30/10/2020 18:47, Theodore Brown wrote:
> > While passing all nested attributes as an array would at least enable
> > consistent semantics, it has the notable disadvantage of preventing
> > some use cases from being expressed in PHP's type system. Specifically,
> > how would you express that an attribute parameter must be passed a
> > single attribute of a particular type?
> 
> I acknowledged this use case, but suspected, and still suspect, that
> it's rarer than the list-of-attributes case.
> 
> > For example, suppose a developer wants to create/use an attribute
> > like the following:
> >
> >     #[Limit(
> >         min: 10,
> >         max: 100,
> >         error: #[CustomError(message: "...", notify: true, withTrace: 
> > false)]
> >     )]
> 
> What is the fundamental advantage of using an attribute as the argument
> here? The same thing can be expressed with an associative array:
> 
>     #[Limit(
>         min: 10,
>         max: 100,
>         error: ["message" => "...", "notify" => true, "withTrace" => false]
>     )]
> 
> The only thing that seems to lose is the ability to specify the allowed
> names and types of options - but those won't be checked by the
> ReflectionAttribute anyway, only once the actual constructor is run.


The fundamental advantage of using an attribute here instead of an
associative array is that it enables IDE autocompletion, and allows
static analyzers to catch any mistakes in the parameter names/types
before the code runs in production.

> So there's nothing really "attribute-y" about the CustomError class,

What do you mean by "attribute-y"? The `CustomError` class would be a
normal attribute, and as such when calling `getArguments()` on the
`Limit` ReflectionAttribute it would return a ReflectionAttribute for
`CustomError`, which would allow its arguments to be inspected without
loading the class.

> and any "static object declaration" syntax would do, e.g.
> 
>     #[Limit(
>         min: 10,
>         max: 100,
>         error: CustomError{message="...", notify=true, withTrace=false}
>     )]

It's not clear what exactly you're proposing here, or how it would work.
E.g. would this still allow inspecting the attribute arguments without
loading the `CustomError` class? Why is a new syntax needed for this?
Would it limit what the `CustomError` constructor is allowed to do? 


> > But if nested attributes are always passed as an array, the `$error`
> > parameter would have to have an `array` type, which provides
> > essentially no context about what is really required. The type system
> > would be perfectly happy to allow an empty array, or an array with
> > multiple values instead of the expected single `CustomError` attribute.
> 
> 
> Again, this is a general problem, not one related to attributes: the
> Symfony validation examples would be best declared as requiring
> "Constraint[] $constraints" rather than "array $constraints".

There is no general problem of not being able to specify that a
parameter takes a single object with a particular type. This would be
an artificial limitation on attributes to patch over the inherent
inconsistency of the grouped syntax for nested attributes.


> > 3. Vote to switch to a less verbose syntax [...]
> >     The downside is that...
> 
> Let me stop you there. The downside is that a mob of Internals regulars
> will come to your house and lynch you for asking them to vote on the
> same thing yet again. It just ain't gonna happen.

I doubt anyone is more tired and worn out from discussing and voting
on attributes than I am. But there are serious issues when it comes to
supporting nested attributes with the #[] syntax and attribute grouping.
Shouldn't I bring them up and propose solutions before PHP 8 is released?

Best regards,  
Theodore

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to