简体   繁体   中英

Doctrine 2 - entity have collection of another entities via key holder table

I want to implement this type of relationship:

在此输入图像描述

Class SimpleUser must have a "languages" class property which should contain list of all SimpleLanguage-s that are binded to the current user in the UserLanguages table.

Please look at the classes:

public class SimpleUser {

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=50)
     */
    private $name;

    // what do I type here? I want to have SimpleLanguage[] here
    private $languages;
}

 public class SimpleLanguage {

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=50)
     */
    private $name;
}

 public class UserLanguages {

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;


/**
 * @var integer
 * @ORM\Column(name="user_id", type="integer")
 */
private $userId;

/**
 * @var integer
 * @ORM\Column(name="language_id", type="integer")
 */
private $languageId;

/**
 * @var SimpleUser
 *
 * @ManyToOne(targetEntity="SimpleUser")
 * @JoinColumn(name="userId", referencedColumnName="id")
 */
private $user;

/**
 * @var SimpleLanguage
 *
 * @ManyToOne(targetEntity="SimpleLanguage")
 * @JoinColumn(name="languageId", referencedColumnName="id")
 */
private $language;
}

First delete $userId; and $languageId from your class UserLanguages ! They are useless, these are properties $user and $language which manage the id of the entity in the database !

Here how to manage languages property in SImpleUser :

use Doctrine\Common\Collections\ArrayCollection;

// ...

class SimpleUser
{
    //...

    /**
     * @ORM\OneToMany(targetEntity="UserLanguages", mappedBy="user")
     */
    protected $languages;

    public function __construct()
    {
        $this->languages = new ArrayCollection();
    }
}

Similar in SimpleLanguage :

use Doctrine\Common\Collections\ArrayCollection;

// ...

class SimpleLanguage
{
    //...

    /**
     * @ORM\OneToMany(targetEntity="UserLanguages", mappedBy="language")
     */
    protected $languages;

    public function __construct()
    {
        $this->languages = new ArrayCollection();
    }
}

EDIT:

I want to have not collection of "UserLanguages" but directly collection of "SimpleLanguage" from the "user_languages" table

Ok currently this is not possible, I think want a ManyToMany relationship instead of a third entity UserLanguages (your question is not very clear) !

Delete the useless entity UserLanguages, and then in SimpleUser :

use Doctrine\Common\Collections\ArrayCollection;

// ...

class SimpleUser
{
    //...

    /**
     * @ORM\ManyToMany(targetEntity="SimpleLanguage", mappedBy="users")
     */
    protected $languages;

    public function __construct()
    {
        $this->languages = new ArrayCollection();
    }
}

And SimpleLanguage :

use Doctrine\Common\Collections\ArrayCollection;

// ...

class SimpleLanguage
{
    //...

    /**
     * @ORM\ManyToMany(targetEntity="SimpleUser", mappedBy="languages")
     * @JoinTable(name="UserLanguages")
     */
    protected $users;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }
}

It will result a third table UserLanguages having user_id and language_id !

You'll be able from user class get the list of all languages linked with one use :

$languages = $user->getLanguages();

Inversely for a language :

$users = $language->getUsers();

You are looking for a uni-directional one-to-many relationship with a join-table which is described in doctrine with the @ManyToMany annotation. This can lead to confusion.

You don't even need the glueing UserLanguages class at all ... doctrine will take care of the table for you.

SimpleUser

/**
 * @ORM\ManyToMany(targetEntity="SimpleLanguage", inversedBy="user")
 * @ORM\JoinTable(name="UserLanguages",
 *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="language_id", referencedColumnName="id", unique=true)}
 * )
 */
 protected $languages;

SimpleLanguage

/**
 * @ORM\ManyToMany(targetEntity="SimpleUser", mappedBy="languages")
 */
 protected $user;

now doctrine will create the UserLanguages table for you and keep the id's ( user_id , language_id ) in there.

Read more on association mappings with a join-table here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM