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

Skip to content

[Validator] Traverse traversables #24577

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
wants to merge 1 commit into from

Conversation

olvlvl
Copy link
Contributor

@olvlvl olvlvl commented Oct 16, 2017

Q A
Branch? 2.8
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
License MIT

Instances such as Doctrine's collections are not traversed because the condition is is_array(). This PR checks for \Traversable too.

I was trying to validate the following:

HelloFresh\RecipeService\Domain\Recipe\Serving:
  properties:
    number:
      - NotBlank: ~

HelloFresh\RecipeService\Domain\Recipe\Recipe:
  properties:
    servings:
      - Valid:
          traverse: true
      - NotBlank: ~

But it kept failing because servings is a ArrayCollection, not an array.

I'm targeting v2.8 but this goes all the way to master. I'm using v3.4.

@olvlvl olvlvl changed the title Traverse traversables [Validator] Traverse traversables Oct 16, 2017
@stof
Copy link
Member

stof commented Oct 16, 2017

No test added to cover this ? This is not a good sign. bug fixes must have a test to prevent regressions

@olvlvl
Copy link
Contributor Author

olvlvl commented Oct 16, 2017

@stof If you think this is indeed a bug, please give me a starting point and I'd gladly write a test.

@olvlvl
Copy link
Contributor Author

olvlvl commented Oct 16, 2017

Tests are failing… if \Traversable is discarded on purpose how does one specify that an instance is traversable? I'm already specifying traverse: true… There's nothing more I can do according to the docs: http://symfony.com/doc/current/reference/constraints/Valid.html#traverse

Or is it that traverse is not recognized properly? Looks like ClassMetadata and GenericMetadata have different opinions:

One is TRAVERSE, the other one IMPLICIT. And the code is not running through ClassMetadata… Could it be it?

@nicolas-grekas nicolas-grekas added this to the 2.8 milestone Oct 16, 2017
@olvlvl
Copy link
Contributor Author

olvlvl commented Oct 17, 2017

I fixed it by adding the following rule:

Doctrine\Common\Collections\ArrayCollection:
  getter:
    values:
      - Valid:
          traverse: true

Not super intuitive… also the error path looks weird:

Object(HelloFresh\RecipeService\Domain\Recipe\Recipe).steps.values[0].images.values[0].link:

@xabbuh
Copy link
Member

xabbuh commented Oct 23, 2017

This does not look like a bug to me. But we could indeed improve the documentation. @olvlvl Would you like to open a PR on https://github.com/symfony/symfony-docs?

However, we could add this as a new feature in 4.1 IMO. But we would need a test and existing tests must not fail then.

@olvlvl
Copy link
Contributor Author

olvlvl commented Oct 25, 2017

@xabbuh is there a way to discard the .values[0] part of the path?

@xabbuh
Copy link
Member

xabbuh commented Nov 2, 2017

@olvlvl What would you expect instead?

@olvlvl
Copy link
Contributor Author

olvlvl commented Nov 8, 2017

I expected ArrayCollection to be traversed without explicitly saying so. But because this is not happening and I use getValues() to validate the items, I have values[*] in the path. Instead of steps.values[0].images.values[0].link I would like to have steps[0].images[0].link. Right now I'm doing a super ugly preg_replace() as I workaround.

@nicolas-grekas
Copy link
Member

The issue with using Traversable is that they are not all rewindable. This means validation would consume the iterator and prevent any further use of it.

@olvlvl
Copy link
Contributor Author

olvlvl commented Jan 16, 2018

@nicolas-grekas You have a very good point here. How about Iterator? They are rewindable.

@jvasseur
Copy link
Contributor

jvasseur commented Jan 16, 2018

Not all Iterators a rewindable (even if they have a rewind method, they sometimes throws exceptions in it). An example of this is Generators that implements the Iterator interface but throws if you call rewind after iterating on it (https://3v4l.org/fmCDO).

EDIT: we could do it for instances of IteratorAgregate since they return a new iterator each time you call getIterator but I don't think it's good DX to support IteratorAgregate without supporting Iterator

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Jan 16, 2018 via email

@nicolas-grekas
Copy link
Member

@olvlvl ok to change to IteratorAggregate and add a test case?

Status: needs work

@ostrolucky
Copy link
Contributor

@nicolas-grekas So, how about I do the same in #25506?

@nicolas-grekas
Copy link
Member

@ostrolucky doable indeed!

@nicolas-grekas
Copy link
Member

@olvlvl OK to finish this one and add a test case ?

@olvlvl
Copy link
Contributor Author

olvlvl commented Feb 5, 2018

@nicolas-grekas Sorry I've been quite busy. I'll try to work on it today.

@nicolas-grekas
Copy link
Member

ping @olvlvl :)

@olvlvl olvlvl force-pushed the olvlvl-validator-traverse branch 2 times, most recently from 7b08244 to bd97f6c Compare February 25, 2018 18:08
@olvlvl olvlvl force-pushed the olvlvl-validator-traverse branch from bd97f6c to 9ca0c49 Compare February 25, 2018 18:10
@olvlvl
Copy link
Contributor Author

olvlvl commented Feb 25, 2018

Hi @nicolas-grekas, I wrote a test to validate an instance of a class implementing IteratorAggregate… and it's working out of the box, without any change, and I don't know why: https://github.com/symfony/symfony/pull/24577/files#diff-d46c902789b437519780ee8110ecb5e9R752.

I had no fun writing these few lines of code. The only documentation I found regarding object validation that do not involve annotation shenanigans was in this issue: #11895 (comment).

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.

7 participants