Eddie
Eddie

Reputation: 119

Symfony2 validation across related entities

I want to use two Doctrine entities for my user registration process: User and Mailaddress (which I keep separated). Users should be able to login using their username (from table User) or their email address (from table Mailaddress).

Unfortunately I can't disallow the @ sign in usernames - which leads to the following problem: If a user registers 2 times...:

  1. with username "whatever" and mail "[email protected]"
  2. with username "[email protected]" and mail "[email protected]"

... I will end up with two users that can't be identified by their respective username or email address anymore. So I need some validation!

Right now I have 2 classes with (almost complete) validation.

Class User (references Mailaddress):

<?php

//...
use AppBundle\Entity\Mailaddress;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Table(name="user", uniqueConstraints={@ORM\UniqueConstraint(name="unique_username", columns={"username"}), @ORM\UniqueConstraint(name="user2mail", columns={"fk_mail"})})
 * @ORM\Entity(repositoryClass="AppBundle\Entity\Repository\UserRepository")
 * @UniqueEntity(
 *   fields={"username"})
 */
class User
{
    /**
     * @Assert\NotBlank(...)
     * @Assert\Length(...)
     * @Assert\Regex(...)
     *
     * @ORM\Column(name="username", type="string", length=100, nullable=false, unique=true)
     */
    private $username;

    //...

    /**
     * @var Mailaddress
     *
     * @Assert\Valid()
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Mailaddress", cascade={"persist"})
     * @ORM\JoinColumn(name="fk_mail", referencedColumnName="id", nullable=false)
     */
    private $obj_mail;

    // ...
}

And class Mailaddress:

<?php

//...
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Table(name="mailaddress", uniqueConstraints={@ORM\UniqueConstraint(name="uniqueEmail", columns={"email"})})
 * @ORM\Entity
 * @UniqueEntity(
 *     fields={"email"})
 */
class Mailaddress
{
    /**
     * @Assert\NotBlank(...)
     * @Assert\Email(...)
     * @Assert\Length(...)
     *
     * @ORM\Column(name="email", type="string", length=100, nullable=false, unique=true)
     */
    private $email;

    // ...
}

All validations are working, mainly the check for uniqueness (no duplicate username and email address).

But how can I validate that

  1. the given email address does not already exist as a username?
  2. the given username does not exist as an email address?

Upvotes: 0

Views: 1279

Answers (1)

vpassapera
vpassapera

Reputation: 362

I think you want a custom constraint: https://symfony.com/doc/current/cookbook/validation/custom_constraint.html

When you're defining it, you're going to have to make database calls, so you'll have to pass it DoctrineManager or an EntityManager if more specific (e.g. arguments: ['@doctrine'] when defining your service)

Upvotes: 1

Related Questions