Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Form] Created FormErrorBag#9099

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
wouterj wants to merge3 commits intosymfony:masterfromwouterj:fix_7205
Closed

Conversation

wouterj
Copy link
Member

QA
Bug fix?no
New feature?yes
BC breaks?yes
Deprecations?yes
Tests pass?yes
Fixed tickets#7205
LicenseMIT
Doc PRsymfony/symfony-docs#3397

The only BC break in this PR is checking it with is_array. Iterating
over the array works just the same as previously:

  • Normally iterating over theRecursiveIterator results in only
    iterating over the errors of the current form.
  • Iterating usingRecursiveIteratorIterator results in iterating over
    all errors recursively.

Todo

  • Adding__toString() support and deprecatingForm::getErrorsAsString().
  • Use this class inForm:getErrors()
  • Fixing tests
  • Use field name as key

*/
protected $errors = array();

private $_invalid = false;
Copy link
Member

Choose a reason for hiding this comment

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

Please remove the leading underscore. We don't use it in Symfony

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I used it because invalid is not a real property of the object, it's just a helper property. But I'll remove it

@wouterj
Copy link
MemberAuthor

I've fixed the tests, added some things for BC (see below) and added the last missing features. I think it's ready for review@stof @bschussek

  • TheFormErrorCollection now also implementsArrayAccess, to be BC with accessing the errors using$errors[1]
  • All fixes in the Validator extension tests are not a proof of BC break, because nobody is going to match the return value ofForm::getErrors() with some expected stuff.
  • TheButtonTypeTests were failing because they passed an array toForm::addError(), I fixed this by converting this array to aFormErrorCollection

*
* @author Wouter J <wouter@wouterj.nl>
*
* @since v2.4.0
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

not sure if this is needed...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but you can changev2.4.0 to2.4.

@stof
Copy link
Member

I think your ArrayAccess is not BC as the offset does not concern only errors but also child error collections. So gettingerrors[1] can give your a FormErrorCollection while it was giving you the second error previously

*/
public function addCollection($formName, $collection)
{
// BC with using arrays with errors
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to support arrays here?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

some tests are failing without this. BTW, do you know why the tests are failing now? It seems there is another BC bug...

@wouterj
Copy link
MemberAuthor

fixed all comments. I know I'm one day after the feature freeze, but I'd like to see this included in 2.4...

@fabpot
Copy link
Member

@wouterj You're lucky as I'm still working on merging the last PRs for 2.4... let's wait for @bschussek thoughts first.

return array_keys($this->errors);
}

public function __toString()
Copy link
Contributor

Choose a reason for hiding this comment

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

missing phpdoc for many methods

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

do we really want to have PHPdoc for PHP build-in methods, like __toString etc?

Copy link
Member

Choose a reason for hiding this comment

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

no

Copy link
Contributor

Choose a reason for hiding this comment

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

yes because otherwise it's not documented what the string representation actually returns

Copy link
Contributor

Choose a reason for hiding this comment

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

and this is one of the main points of FormErrorBag

Copy link
Contributor

Choose a reason for hiding this comment

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

also its not doccumented that it accepts a parameter

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

the string representation wasn't documented on getErrorsAsString() too, I don't really know why we should do it here. And the parameter is only for internal use.

Copy link
Contributor

Choose a reason for hiding this comment

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

where is the parameter used internally?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

It's used to indent the children forms with 4 spaces

Copy link
Contributor

Choose a reason for hiding this comment

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

ok as long as its not used outside the class

2.4.0
-----

* changed getErrors() to return a FormErrorBag, which is countable,
Copy link
Contributor

Choose a reason for hiding this comment

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

missing bc break info

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

what i also mean is that it should be tagged with [BC BREAK], see other changelog entries

Copy link
Contributor

Choose a reason for hiding this comment

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

also getErrors now returns all errors, whereas it previously returned only direct child errors, or?

Copy link
Member

Choose a reason for hiding this comment

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

@Tobion no it does not. It returns a RecusiveIterator instead of an array. So youcan have all errors if you wrap it in aRecursiveIteratorIterator, but the default iteration still gives you only the form errors only (and not the direct child errors as you said in your comment)

@asm89
Copy link
Contributor

@fabpot @bschussek Any chance of getting this in2.4?

}

return $errors;
return (string) $this->getErrors();
Copy link
Contributor

Choose a reason for hiding this comment

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

it should be$this->getErrors()->__toString($level)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

why? Level should be the default, 0, and explicitly calling a magic method seems wrong to me. But if there is any reason why this is better or if this is the CS, I'm happy to change this

Copy link
Member

Choose a reason for hiding this comment

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

@wouterj because if you ignore the$level argument, you are not providing BC totally (even if it was considered as an internal argument, I'm sure some people were using it)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

fixed

@hugohenrique
Copy link
Contributor

ping

@asm89
Copy link
Contributor

ping@fabpot @bschussek I guess this won't make 2.4...

@Koc
Copy link
Contributor

Koc commentedDec 11, 2013

is it possible to convert this bag to array like

'metal_companiesbundle_company[companyPhones][1][phone]' =>     array (size=1)      0 => string 'Error description.'

?

Where key is form field full name and value is list of the errors for field. It is useful for ajax responses (bind tooltips with errors to fields)

@wouterj
Copy link
MemberAuthor

@Koc no, that's not possible with the method itself. But with some array changer functions, you can create something like that.

}

return $errors;
}

/**
* @deprecated Deprecated since version 2.4, to be removed in 3.0. Covert
Copy link
Member

Choose a reason for hiding this comment

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

should be 2.5 andConvert instead ofCovert.

Copy link
Member

Choose a reason for hiding this comment

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

Also, can you put everything on the same line?

@fabpot
Copy link
Member

@wouterj Besides some small typos, looks good to me. Can you also rebase on current master and add a ticket for the documentation? Thanks.

This is fully BC with returning an array and it deprecatesForm::getErrorsAsString()
@wouterj
Copy link
MemberAuthor

@fabbot everything is now fixed and rebased

@wouterj
Copy link
MemberAuthor

doc issue:symfony/symfony-docs#3397

@fabpot
Copy link
Member

apparently, tests are broken

@wouterj
Copy link
MemberAuthor

I'm now stuck... Maybe someone can help me?

When using the RecursiveIterator directly, it should only return theFormError instances in the root of the array and not theFormError instances in theFormErrorBag. This all works fine in thecurrent method, we just skip the value when it's an instance ofFormErrorBag and see if the next one is aFormError instance.

However, in thevalid method, we can't do it that way. If we skip theFormErrorBag instances in that method and only return true when the next element exists and it is aFormError instance, we can't recursively traverse over the child form errors.

ImagineFormErrorBag::$errors contains this:

array(    [0] =>FormError instance (...),    [child] =>FormErrorBag instance (...))

When iterating, the following things happen:

  1. FormErrorBag::valid() is called and returnstrue,[0] exists
  2. FormErrorBag::current() is called and returns[0] element
  3. FormErrorBag::next() is called and sets the pointer to the next element
  4. FormErrorBag::valid() is called and returnstrue,[child] exists
  5. FormErrorBag::current() is called and returns[child]

In the 5th step it should not have returned theFormErrorBag object, but it can't do nothing else. Thevalid method already said the element exists and thecurrent method has to return aFormError object. It can't go to the next element, as there is no next element.

How can we fix this, so that the 5th step isn't executed? We can't add a test on instance in thevalid method...

@igorw
Copy link
Contributor

From what I can tell, you really have two different cases. And you should not be trying to make both work with the same iterator instance.

The original iterator is a FormErrorBag that may recursively contain other FormErrorBag instances. I'll call it$errors. Here's the two cases:

Case A is looking at the top level errors only. In simple terms, this meansfilter('isFormError', $errors), whereisFormError checks forinstanceof FormError.

Case B is recursively walking over over the nestedFormErrorBag instances (which happen to implement Iterator) and as such you can use aRecursiveIterator. Or in a different sense, you are flattening the nested list-of-lists to a list of FormError elements.

So what you really want isFormErrorBag to contain two methods. OnegetTopLevelErrors() that returns itself wrapped inside aFilterIterator. And agetAllErrors() that returns itself wrapped inside a flatteningRecursiveIterator.

@igorw
Copy link
Contributor

After looking at the current implementation I can also pinpoint the problem. It is callingnext() from withinvalid(). It is using recursion on a mutable object which is going to cause lots of problems because it actually already advances the iterator while you are checking the validity.

What it comes down to is this. Currently, you are trying to do the recursion insideFormErrorBag directly, instead of wrapping it inside aRecursiveIterator, which would keep that responsibility separate.

@wouterj
Copy link
MemberAuthor

I think you right@igorw we can't mix them into one class. It would be nice if we could though...

However, we have to be BC with an array, so I propose to have aFormErrorBag which extendsArrayIterator (or we keep the current implementation). And it has a methodgetAllErrors() which returns aRecursiveArrayIterator.

@bschussek I'd love to hear your opinion about this.

🎆

@wouterj
Copy link
MemberAuthor

Closing in favor of#9914

@wouterjwouterj deleted the fix_7205 branchDecember 31, 2013 14:12
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers
No reviews
Assignees
No one assigned
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

11 participants
@wouterj@stof@fabpot@asm89@hugohenrique@Koc@igorw@staabm@webmozart@mvrhov@Tobion

[8]ページ先頭

©2009-2025 Movatter.jp