1

I have a classic form with fields : 'username', 'password' and 'birthday'.

Here are my asserts for validation (in my User entity) :

.....

/**
 * @var string
 * @Assert\NotBlank(message="username.error.blank")
 * @Assert\MinLength(limit="2", message="username.error.short")
 */
protected $username;

/**
 * @var string
 * @Assert\NotBlank(message="password.error.blank")
 * @Assert\MinLength(limit="4", message="password.error.short")
 */
protected $password;

/**
 * @Assert\True(message="password.error.different")
 */
public function isPasswordLegal()
{
    return ($this->username != $this->password);
}

The problem is that when I submit the form when it is totally empty :

  • 'username' : error message because it is blank (ok)
  • 'password' : error message because it is blank (ok)
  • 'password' : error message because it is the same as username (here is the problem !)

So, 2 questions :

  1. How to solve this 'display' problem ?
  2. How to display this message next to 'password' field with the {{ form_errors(form.password) }} ?

Thanks for your help :-)

Aurel

2 Answers 2

6

Answer 1: Use a GroupSequence.

/**
 * @Assert\GroupSequence({"User", "Strict"})
 */
class User
{
    /**
     * @Assert\True(message="password.error.different", groups="Strict")
     */
    public function isPasswordLegal()
    {
        return ($this->username != $this->password);
    }

This will first validate all constraints in group "User". Only if all constraints in that group are valid, the second group, "Strict", will be validated, to which I added your custom validation method.

To explain, why "User" contains all other constraints, I need to elaborate a bit more:

  1. Each constraint that has no explicit groups set belongs to group "Default"
  2. Each constraint that belongs to group "Default" also belongs to group "{ClassName}", i.e. a group named like the class on which the constraint is defined ("User" in our case).
  3. When you validate an object in group "{ClassName}", all constraints in group "{ClassName}" are validated (i.e. all constraints in group "Default")
  4. When you validate an object in group "Default", all constraints in group "Default" are validated, UNLESS:
    • The class defines a group sequence. In that case, the groups in the group sequence will be validated in order.

Thus, group sequences cannot contain the group "Default" (this would create a cycle), but need to contain the group "{ClassName}" instead.

Answer 2: Use the "error_mapping" option (only if on latest Symfony master).

class UserType
{
    public function getDefaultOptions()
    {
        return array(
            'data_class' => '...\User',
            'error_mapping' => array(
                'passwordLegal' => 'password',
            ),
        );
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

A1. This one is easy enough though I guess it might be a bit redundant:

public function isPasswordLegal()
{
    // This is okay because the isBlank assert will fail
    if (!$this->password) return true;

    return ($this->username != $this->password);
}

A2. As far as displaying goes, something like:

 {{ form_label (form.username) }}{{ form_widget(form.username) }}{{ form_errors(form.username) }}

 {{ form_label (form.password) }}{{ form_widget(form.password) }}{{ form_errors(form.password) }}

Style as needed.

1 Comment

Almost perfect. A1 is Ok, but A2 does not display the error message related to method "isPasswordLegal" close to password field...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.