Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[OptionsResolver] Add support for array<> syntax to validate keys #59442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

VincentLanglet
Copy link
Contributor

@VincentLanglet VincentLanglet commented Jan 8, 2025

Q A
Branch? 7.3
Bug fix? no
New feature? yes
Deprecations? no
Issues Fix #...
License MIT

In PHPdoc there is three way to describe an generic array:

  • string[]
  • array<string>

The second syntax has the benefit to allows describing the keys (for instance array<string, string>) so I'd like to add the support for this syntax in the OptionResolver.

Require #59441 first.

The next step would be the support for the array{foo: string, bar?: int} syntax, but this might be a little bit more complicated and should be done in another PR anyways.

@carsonbot carsonbot added this to the 7.3 milestone Jan 8, 2025
@nicolas-grekas nicolas-grekas changed the title [Options Resolver] Add support for array<> syntax to validate keys. [OptionsResolver] Add support for array<> syntax to validate keys Jan 9, 2025
Copy link
Contributor

@OskarStark OskarStark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebase needed after the whitespace PR

@VincentLanglet
Copy link
Contributor Author

Rebase needed after the whitespace PR

Rebased

Copy link
Member

@yceruto yceruto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great to have! However, I'm not sure adding support for anything other than array<int|string, X> is a good idea, as a shorter and simpler alternative is already supported

public function testNestedArrays2()
{
$this->resolver->setDefined('foo');
$this->resolver->setAllowedTypes('foo', 'array<array<int>>');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as int[][] (shorter and simpler to write/read)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. It's just to prove the second syntax works. (Same for others)

public function testResolveTypedArrayWithUnion2()
{
$this->resolver->setDefined('foo');
$this->resolver->setAllowedTypes('foo', 'array<string|int>');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as (string|int)[] (more less the same complexity)

public function testResolveTypedArray2()
{
$this->resolver->setDefined('foo');
$this->resolver->setAllowedTypes('foo', 'array<string>');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as string[] (shorter and simpler to write/read)

public function testResolveTypedWithUnionOfArray2()
{
$this->resolver->setDefined('foo');
$this->resolver->setAllowedTypes('foo', 'array<string|int>|array<bool|int>');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as (string|int)[] | (bool|int)[]

public function testNestedArraysWithUnions2()
{
$this->resolver->setDefined('foo');
$this->resolver->setAllowedTypes('foo', 'array<int|float|array<int|float>>');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as (int|float|(int|float)[])[] (more less same complexity)

@yceruto
Copy link
Member

yceruto commented Jan 9, 2025

The next step would be the support for the array{foo: string, bar?: int} syntax, but this might be a little bit more complicated and should be done in another PR anyways.

I don't think it will be necessary, as nested option definitions can currently handle that

@VincentLanglet
Copy link
Contributor Author

It's great to have! However, I'm not sure adding support for anything other than array<string, X> is a good idea, as a shorter and simpler alternative is already supported

It's debatable:

First array<int, X> need to be supported because array<int, X> is not the same as X[] (which means array<int|string, X>). In the same way people might want a array<numeric, X> (but it feel weird).

Secondly, people might prefer one syntax over another, especially when dealing with multiple options with arrays:

  • array<int|string, X> might be preferred over X[] because it's explicit...
  • array might be preferred over X[] to always use array<> syntax with or without keys...

Also, if one day we plan to introduce more "types" like non-empty-string or positive-integer,
the current implementation will require no extra work to support them as array-key.

Or do you mean you're ok with keeping the current implementation but removing some tests @yceruto ?
I would like to offer a BC promise on the fact array<X> will stay valid because it's became an usual syntax for phpdoc.

@VincentLanglet
Copy link
Contributor Author

This PR is mark as "Need works".

Friendly ping @yceruto just to be sure you saw my answer
#59442 (comment)

I'm unsure about the "work needed" atm since I'd like to support both array<X, Y> and array<Y>

@mtarld
Copy link
Contributor

mtarld commented Jan 13, 2025

I wonder if at some point it'd be easier to leverage the StringTypeResolver of TypeInfo, as it does what you're trying to achieve. The only downside it that it requires the phpstan/phpdoc-parser library to work.

@VincentLanglet
Copy link
Contributor Author

I wonder if at some point it'd be easier to leverage the StringTypeResolver of TypeInfo, as it does what you're trying to achieve. The only downside it that it requires the phpstan/phpdoc-parser library to work.

Indeed that would be great. I didn't know such component already existed.
But is it possible without changing the constructor of OptionResolver ?

@yceruto
Copy link
Member

yceruto commented Jan 13, 2025

In the same way people might want a array<numeric, X>

Only strings or integers are supported anyway, so I'd throw an exception if anything other than string|int is configured as an array key.

I'm okay with full array<> support if there's no better way to define the array key.

@VincentLanglet
Copy link
Contributor Author

In the same way people might want a array<numeric, X>

Only strings or integers are supported anyway, so I'd throw an exception if anything other than string|int is configured as an array key.

It's not only string or integer. You can also allow numeric.
And technically, 'long', 'integer', 'scalar' are working.
And any union of all these types should work too.

So adding a check would add some complexity with no real benefit, because if someone use

array<bool, int>

for instance, there will be already an exception since keys are not bool. "Expected bool, got int".
Which allow the developper to see his mistake.

In the same way that ->addAllowedType('foo', 'strin') will throw an exception, when using the option "Expected strin, got string".

The configuration validation as only interested if the validation was made on the addAllowedType call ; which is not the case (you're asking for doing it at the option resolving).

I can add a test with array<bool, int> if you want @yceruto to prove it

@stof
Copy link
Member

stof commented Jan 14, 2025

@VincentLanglet PHP arrays don't support anything else than integers or strings as array keys. numeric would allow floats, while they are not valid keys.
regarding integer, this is treated as an alias of int IIRC, so we would still support it for consistent.

@VincentLanglet
Copy link
Contributor Author

@VincentLanglet PHP arrays don't support anything else than integers or strings as array keys. numeric would allow floats, while they are not valid keys. regarding integer, this is treated as an alias of int IIRC, so we would still support it for consistent.

The option resolver will be validating existing array-key.
So numeric won't allow floats since it's not possible to set a float as array key.
But it will accepts floats as array-key which is int|numeric-string and different from int|string because stricter.

@chalasr
Copy link
Member

chalasr commented Jan 16, 2025

I wonder if at some point it'd be easier to leverage the StringTypeResolver of TypeInfo, as it does what you're trying to achieve. The only downside it that it requires the phpstan/phpdoc-parser library to work.

Makes sense to me. Should we stop building another type parser in this component to look into this instead?

@mtarld
Copy link
Contributor

mtarld commented Jan 17, 2025

Maybe we can:

  • if phpstan/phpdoc-parser is installed, leverage the TypeInfo component and process complex type strings
  • otherwise, process only simple type strings (and throw a meaningful exception message telling to install phpstan/phpdoc-parser when a complex type is defined)

WDYT?

@VincentLanglet
Copy link
Contributor Author

Maybe we can:

  • if phpstan/phpdoc-parser is installed, leverage the TypeInfo component and process complex type strings
  • otherwise, process only simple type strings (and throw a meaningful exception message telling to install phpstan/phpdoc-parser when a complex type is defined)

WDYT?

I agree.

Should I close this PR or array<> syntax is considered simple enough for being processed without phpstan/phpdoc-parser @yceruto @mtarld @chalasr ?

@chalasr
Copy link
Member

chalasr commented Feb 7, 2025

I would suggest reworking this PR according to the proposed plan :)

@yceruto
Copy link
Member

yceruto commented Feb 7, 2025

Maybe we can:

  • if phpstan/phpdoc-parser is installed, leverage the TypeInfo component and process complex type strings
  • otherwise, process only simple type strings (and throw a meaningful exception message telling to install phpstan/phpdoc->parser when a complex type is defined)

WDYT?

I agree too 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants