🎻

[Symfony/Validation] Callback制約の使い方

2020/07/24に公開約1,600字

普通のバリデーション

Symfonyにおいて、フォーム経由で作成されたエンティティをバリデーションする方法はいくつかありますが、最も一般的なのはエンティティのプロパティにアノテーションで書く方法だと思います。

use Symfony\Component\Validator\Constraints as Assert;

class User
{
    /**
     * @Assert\NotBlank()
     */
    private $name;

    /**
     * @Assert\NotBlank()
     * @Assert\Email()
     */
    private $email;
    
    /**
     * @Assert\NotBlank()
     */
    private $password;
}

他のプロパティの値を使ったバリデーションをしたいとき

では、例えば nameemail の文字列に含まれるような文字列は password にはセットできない」 というバリデーションを書きたければどうすればいいでしょうか?

1. カスタムバリデーションを作る

symfony/formで「どちらか片方の入力は必須、かつ両方入力はNG」をバリデーションする

こちらの過去記事でも紹介したようにカスタムバリデーションを作ればもちろん実装できます。

2. Callback制約を使う

が、もう少し手軽な方法として Callback制約 というのが用意されているので、今回はこれを使っていみたいと思います。

Callback 制約は、他の制約と違って プロパティではなくメソッドにアノテートします。

それにより、そのメソッドがバリデーション実行時にコールされるようになるというものです。

use Symfony\Component\Validator\Constraints as Assert;

class User
{
    /**
     * @Assert\NotBlank()
     */
    private $name;

    /**
     * @Assert\NotBlank()
     * @Assert\Email()
     */
    private $email;
    
    /**
     * @Assert\NotBlank()
     */
    private $password;
    
    /**
     * @Assert\Callback()
     */
    public function validatePassword(ExecutionContextInterface $context)
    {
        if (strpos($this->name, $this->password) !== false || strpos($this->email, $this->password) !== false) {
            $context->buildViolation('名前やメールアドレスに含まれる文字列はパスワードに設定できません')->atPath('password')->addViolation();
        }
    }
}

こんな感じです。便利ですね🙌

GitHubで編集を提案

Discussion

ログインするとコメントできます