Home » Php » php – Doctrine @UniqueEntity with ManyToOne fields?

php – Doctrine @UniqueEntity with ManyToOne fields?

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m trying to create a UniqueEntity with 2 fields (both are ManyToOne fields).

The code is as follow:

/*
* @ORM\Table()
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
* @UniqueEntity(fields={"user", "connect"})
*/
class UserConnect
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var boolean $isLeader
     *
     * @ORM\Column(name="isLeader", type="boolean")
     */
    private $isLeader;

    /**
     * @var date $joinedDate
     *
     * @ORM\Column(name="joinedDate", type="date")
     */
    private $joinedDate;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="userConnects")
     * 
     */
    private $user;

    /**
     * @ORM\ManyToOne(targetEntity="Connect", inversedBy="userConnects")
     * 
     */
     private $connect;

The goal is to ensure that I’ve got only one Entity that link a USER with a CONNECT.

Should I write something else in my @UniqueEntity declaration?

How to&Answers:

I understand you want to get an error only when both user and connect fields for one record are duplicated in other record in the database.

The @UniqueEntity annotation is rightly declared for your purpose (multiple column index) but only will be triggered in the form validation and doesn’t affects the DDBB schema.

If you want to add the same check at database level you should use the @UniqueConstraint annotation in the Table() declaration and give a name to the new index. Something like:

/*
* @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(name="IDX_USER_CONNECT", columns={"user_id", "connect_id"})})
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
* @UniqueEntity(fields={"user", "connect"})
*/
class UserConnect
{

In the other hand, if you declare @ORM\Column(unique=true) in each attribute you will get a very different behavior, it won’t be a multiple column index but you will have two independent unique columns, if you enter twice the same user_id you will get an error independently of the connect_id value, and the same will happens if you enter twice the same connect_id value.

Answer:

This works:

/**
 * State
 *
 * @ORM\Table(
 *  name="general.states",
 *  uniqueConstraints={
 *      @ORM\UniqueConstraint(name="states_country_name_code_key", columns={"idcountry", "name","code"}),
 *  })
 * @ORM\Entity(repositoryClass="Fluency\Bundle\GeneralBundle\Entity\Repository\StateRepository")
 */
class State
{.......

Taken from an entity on my system. This way affects Database schema. See where i put @\ORM\UniqueConstraint annotation. Sorry @estopero… next time i must read first the other answers.

Answer:

you should add the unique declaration in your attributes annotations too.

 /**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="userConnects")
 * @ORM\Column(unique=true)
 */
private $user;

/**
 * @ORM\ManyToOne(targetEntity="Connect", inversedBy="userConnects")
 * @ORM\Column(unique=true)
 */
 private $connect;

See this symfony doc and this StackOverflow answer.