Zwen2012
Zwen2012

Reputation: 3498

Symfony: Assert/Length Ignore Whitespace

I have a Model and an attribute $test. I have an annotation for an assert Max-length. But I don't want to count the whitespaces, only the characters. So the text MUST have 40 characters and not a mix of 40 characters with whitespace. Is this possible?

/**
     * @var string
     *
     * @Assert\NotBlank(message = "text.length.error")
     * @Assert\Length(
     *      max = 40,
     *      maxMessage = "Only 40 letters."
     * )
     */
    protected $text;

Upvotes: 1

Views: 2157

Answers (2)

miikes
miikes

Reputation: 974

You can create your own Constraint:

CharacterLength.php

namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class CharacterLength extends Constraint
{
    public $max;
    public $maxMessage;
}

CharacterLengthValidator.php

namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class CharacterLengthValidator extends ConstraintValidator
{
    /**
     * @param string $text
     * @param Constraint $constraint
     */
    public function validate($text, Constraint $constraint)
    {
        if (strlen(str_replace(" ", "", $text)) > $constraint->max) {
            $this->context
                ->buildViolation($constraint->maxMessage)
                ->addViolation();
        }
    }
}

YourEntity.php

use AppBundle\Validator\Constraints\CharacterLength;

/**
 * @var string
 *
 * @CharacterLength(
 *      max = 40,
 *      maxMessage = "Only 40 letters."
 * )
 */
protected $text;

Upvotes: 1

Tobias Xy
Tobias Xy

Reputation: 2069

Well the LengthValidator class is using the mb_strlen function to determine the length. If you want to use the amount of non-whitespace characters for validation you need to create a custom validator.

The annotation:

/**
 * @var string
 *
 * @Assert\NotBlank(message = "text.length.error")
 * @Assert\Callback("validate")
 */
protected $text;

The validation method (in the same class):

public function validate(ExecutionContextInterface $context) {
    if (40 > strlen(str_replace(" ", "", $this->text))) {
        $context->buildViolation('Only 40 letters.')
            ->atPath('text')
            ->addViolation();
    }
}

The parameter of this metod is an instance of Symfony\Component\Validator\Context\ExecutionContextInterface, make sure to import it at the top of the file.

For more information (e.g. how to put the validation into a separate class) check the symfony documentation.

Upvotes: 2

Related Questions