Aurel
Aurel

Reputation: 796

Symfony2 : dependency between validation asserts

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 :

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

Upvotes: 1

Views: 1989

Answers (2)

Bernhard Schussek
Bernhard Schussek

Reputation: 4841

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',
            ),
        );
    }
}

Upvotes: 6

Cerad
Cerad

Reputation: 48865

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.

Upvotes: 1

Related Questions