Skip to content

[DX][Form][Validator] Add ability check if cocrete constraint fails. #19496

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

Merged
merged 1 commit into from
Mar 22, 2017

Conversation

Koc
Copy link
Contributor

@Koc Koc commented Aug 1, 2016

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? wait for travis
Fixed tickets #15154
License MIT
Doc PR should open

Sometimes for big forms with multiple constraints we should handle some errors separately.

// when using validator
$constraintViolations = $validator->validate(...);
if (count($constraintViolations->findByCodes(UniqueEntity::NOT_UNIQUE_ERROR))) {
  // display some message or send email or etc
}

// when using forms
if (count($form->getErrors()->findByCodes(UniqueEntity::NOT_UNIQUE_ERROR))) {
  // display some message or send email or etc
}

This PR add some useful methods to handle this. Before we should iterate all failed constraints using foreach.

Feel free to suggest better names for new methods.

@carsonbot carsonbot added Status: Needs Review DX DX = Developer eXperience (anything that improves the experience of using Symfony) Form Validator Feature labels Aug 1, 2016
@@ -265,6 +266,16 @@ public function seek($position)
}
}

public function getFormErrorByCode($code)
Copy link
Contributor

@HeahDude HeahDude Aug 1, 2016

Choose a reason for hiding this comment

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

What about hasErrorCode? And what if there are many errors with the same code?

I suggest either to return a boolean: false => no such error, true => error(s), or empty array/array of error(s).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@HeahDude I would prefer return array/empty array, what name give for this method?

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe just add an "s" to error

Copy link
Contributor

@ro0NL ro0NL Aug 7, 2016

Choose a reason for hiding this comment

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

FormErrorIterator::getFormErrorsByCode duplicates terms, the context is clear due the class name. We're dealing with form errors. Ie. you could go with FormErrorIterator::getByCode or maybe findByCode.

However if we can get a new FormErrorIterator instance for one or more codes that would be truly convenient.. ie.
$specificErrros = $errors->withCodes(array(Constraint::CODE, OtherConstraint::CODE));

For quick one-liners, you could consider adding hasCode.

@Koc
Copy link
Contributor Author

Koc commented Aug 2, 2016

//cc @webmozart

@Koc Koc force-pushed the get-errors-by-code branch from 19d66ba to f3e2159 Compare September 21, 2016 16:10
{
$violations = array();
foreach ($this as $violation) {
if (in_array($violation->getCode(), $codes, true)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

$codes should be casted to array. Imo this may also be typehinted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ro0NL I've added support passing code or array of codes. No need wrap single code with array

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally i'd favor API like

final public function findByCode($code)
{
   return $this->findByCodes(array($code));
}

public function findByCodes(array $codes)
{ }

But this is fine 👍

@Koc Koc force-pushed the get-errors-by-code branch 2 times, most recently from c2e1323 to 5eb0822 Compare September 24, 2016 10:18
public function findByCodes($codes)
{
$codes = (array) $codes;
$formErrors = array();
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be $errors

{
$codes = (array) $codes;
$formErrors = array();
foreach ($this as $formError) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be $error

*
* @return static New instance which contains only specific errors.
*/
public function findByCodes($codes)
Copy link
Contributor

Choose a reason for hiding this comment

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

As this only works for errors caused by the validator component...im not sure coupling hardcoded is appropriate. It's convenient though.. but maybe this should be findByCause..

$errros->findByCause(function($cause) use ($codes) {
    return $cause instanceof ConstraintViolation && in_array($cause->getCode(), (array) $codes, true);
});

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't see any benefits from public method findByCause - too much code for writing closure. It equals to writing foreach.

@Koc Koc force-pushed the get-errors-by-code branch from 5eb0822 to 29a3a7e Compare September 24, 2016 20:11
@Koc
Copy link
Contributor Author

Koc commented Sep 28, 2016

@fabpot @webmozart tests pass, examples have updated

$form->addError(new FormError('Error 2!', null, array(), null, $cause));
$cause = new ConstraintViolation('Error 3!', null, array(), null, '', null, null, 'code2');
$form->addError(new FormError('Error 3!', null, array(), null, $cause));
$formErrors = $form->getErrors();
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps should be tested with nested errors.

@nicolas-grekas nicolas-grekas added this to the 3.x milestone Dec 6, 2016
@fabpot
Copy link
Member

fabpot commented Mar 22, 2017

Thank you @Koc.

@fabpot fabpot merged commit 29a3a7e into symfony:master Mar 22, 2017
fabpot added a commit that referenced this pull request Mar 22, 2017
…straint fails. (Koc)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DX][Form][Validator] Add ability check if cocrete constraint fails.

| Q | A |
| --- | --- |
| Branch? | master |
| Bug fix? | no |
| New feature? | yes |
| BC breaks? | no |
| Deprecations? | no |
| Tests pass? | wait for travis |
| Fixed tickets | #15154 |
| License | MIT |
| Doc PR | should open |

Sometimes for big forms with multiple constraints we should handle some errors separately.

``` php
// when using validator
$constraintViolations = $validator->validate(...);
if (count($constraintViolations->findByCodes(UniqueEntity::NOT_UNIQUE_ERROR))) {
  // display some message or send email or etc
}

// when using forms
if (count($form->getErrors()->findByCodes(UniqueEntity::NOT_UNIQUE_ERROR))) {
  // display some message or send email or etc
}
```

This PR add some useful methods to handle this. Before we should iterate all failed constraints using foreach.

Feel free to suggest better names for new methods.

Commits
-------

29a3a7e Add ability retrieve errors by their code.
@nicolas-grekas nicolas-grekas modified the milestones: 3.x, 3.3 Mar 24, 2017
@fabpot fabpot mentioned this pull request May 1, 2017
@Koc Koc deleted the get-errors-by-code branch July 22, 2019 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature Form Status: Needs Review Validator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants