🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-one-unidirectional 以下文单抄字doctrine的官方网站,稍翻译一下。 ~~~ CREATE TABLE User ( id INT AUTO_INCREMENT NOT NULL, address_id INT DEFAULT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE Address ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE User ADD FOREIGN KEY (address_id) REFERENCES Address(id); ~~~ 1多对一 User 跟address的关系是多对一,即多个user可以属于同一个地址, entity的映射关系如下: ~~~ <?php /** @Entity */ class User { // ... /** * Many Users have One Address. * @ManyToOne(targetEntity="Address") * @JoinColumn(name="address_id", referencedColumnName="id") */ private $address; } /** @Entity */ class Address { /** * @var integer * * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; } ~~~ @JoinColumn(name="address_id", referencedColumnName="id")这一句就是建立了自身的address_id跟 Address表的名字为id的关系,address的id是指@ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)。 2 一对一 不可逆 表结构: ~~~ CREATE TABLE Product ( id INT AUTO_INCREMENT NOT NULL, shipping_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_6FBC94267FE4B2B (shipping_id), PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE Shipping ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE Product ADD FOREIGN KEY (shipping_id) REFERENCES Shipping(id); ~~~ 即一个product有一个shipping 一个产品有一个发货单 ~~~ <?php <?php /** @Entity */ class Product { // ... /** * One Product has One Shipping. * @OneToOne(targetEntity="Shipping") * @JoinColumn(name="shipping_id", referencedColumnName="id") */ private $shipping; // ... } /** @Entity */ class Shipping { /** * @var integer * * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; } ~~~ 同理这里的shipping_id是表名$shipping对应的是shipping_id,也就是在表名的字段shipping_id, 3 一对一 双向的 表结构如下: ~~~ CREATE TABLE Cart ( id INT AUTO_INCREMENT NOT NULL, customer_id INT DEFAULT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE Customer ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE Cart ADD FOREIGN KEY (customer_id) REFERENCES Customer(id); ~~~ 也即二个entity都定义了OneToOne ~~~ <?php /** @Entity */ class Customer { // ... /** * One Customer has One Cart. * @OneToOne(targetEntity="Cart", mappedBy="customer") */ private $cart; // ... } /** @Entity */ class Cart { // ... /** * One Cart has One Customer. * @OneToOne(targetEntity="Customer", inversedBy="cart") * @JoinColumn(name="customer_id", referencedColumnName="id") */ private $customer; // ... } ~~~ 4 一对一关系 内部的 指一张表内的关系 结构: ~~~ CREATE TABLE Student ( id INT AUTO_INCREMENT NOT NULL, mentor_id INT DEFAULT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE Student ADD FOREIGN KEY (mentor_id) REFERENCES Student(id); ~~~ mentor为帮助的意思,即一个学生找另一个学生帮助,可能这意思,并且一个学生只能帮助一个人?自己的理解打了一个问口号。 ~~~ <?php /** @Entity */ class Student { // ... /** * One Student has One Student. * @OneToOne(targetEntity="Student") * @JoinColumn(name="mentor_id", referencedColumnName="id") */ private $mentor; // ... } ~~~ 5 一对多的对向关系 One-To-Many, Bidirectional¶ ~~~ CREATE TABLE Product ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE Feature ( id INT AUTO_INCREMENT NOT NULL, product_id INT DEFAULT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE Feature ADD FOREIGN KEY (product_id) REFERENCES Product(id); ~~~ Feature指特性,可能是指产品有很多特性,色彩重量一类的。 ~~~ <?php use Doctrine\Common\Collections\ArrayCollection; /** @Entity */ class Product { // ... /** * One Product has Many Features. * @OneToMany(targetEntity="Feature", mappedBy="product") */ private $features; // ... public function __construct() { $this->features = new ArrayCollection(); } } /** @Entity */ class Feature { // ... /** * Many Features have One Product. * @ManyToOne(targetEntity="Product", inversedBy="features") * @JoinColumn(name="product_id", referencedColumnName="id") */ private $product; // ... } ~~~ 注意在Product中的构造函数中加入了: public function __construct() { $this->features = new ArrayCollection(); } 可以把特性以arraycollection读取现来。 6 一对多 非双向的以join 命令创建的关联 One-To-Many, Unidirectional with Join Table 表结构: ~~~ CREATE TABLE User ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE users_phonenumbers ( user_id INT NOT NULL, phonenumber_id INT NOT NULL, UNIQUE INDEX users_phonenumbers_phonenumber_id_uniq (phonenumber_id), PRIMARY KEY(user_id, phonenumber_id) ) ENGINE = InnoDB; CREATE TABLE Phonenumber ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE users_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES User(id); ALTER TABLE users_phonenumbers ADD FOREIGN KEY (phonenumber_id) REFERENCES Phonenumber(id); ~~~ 其实这是三张表的关系了,加了中间表:users_phonenumbers ,其中的user_id 跟user中的id关联,phonenumber_id跟phonenumber表的id关联。 ~~~ <?php /** @Entity */ class User { /** * Many User have Many Phonenumbers. * @ManyToMany(targetEntity="Phonenumber") * @JoinTable(name="users_phonenumbers", * joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="phonenumber_id", referencedColumnName="id", unique=true)} * ) */ private $phonenumbers; public function __construct() { $this->phonenumbers = new \Doctrine\Common\Collections\ArrayCollection(); } // ... } /** @Entity */ class Phonenumber { // ... } ~~~ 7.一对多自关联 One-To-Many, Self-referencing¶ 表结构如下: ~~~ CREATE TABLE Category ( id INT AUTO_INCREMENT NOT NULL, parent_id INT DEFAULT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE Category ADD FOREIGN KEY (parent_id) REFERENCES Category(id); ~~~ 对应的entity关系的创建如下: ~~~ <?php /** @Entity */ class Category { // ... /** * One Category has Many Categories. * @OneToMany(targetEntity="Category", mappedBy="parent") */ private $children; /** * Many Categories have One Category. * @ManyToOne(targetEntity="Category", inversedBy="children") * @JoinColumn(name="parent_id", referencedColumnName="id") */ private $parent; // ... public function __construct() { $this->children = new \Doctrine\Common\Collections\ArrayCollection(); } } ~~~ children是我们建的一个属性,用来保存下面的子菜单 这里又要加入__construct。 8. 多对多关系 不可逆 也即非双向 Many-To-Many, Unidirectional¶ 表结构: ~~~ CREATE TABLE User ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE users_groups ( user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id) ) ENGINE = InnoDB; CREATE TABLE Group ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; ALTER TABLE users_groups ADD FOREIGN KEY (user_id) REFERENCES User(id); ALTER TABLE users_groups ADD FOREIGN KEY (group_id) REFERENCES Group(id); ~~~ 这里有一张users_group表为中间表。 entity的关系如下: ~~~ <?php /** @Entity */ class User { // ... /** * Many Users have Many Groups. * @ManyToMany(targetEntity="Group") * @JoinTable(name="users_groups", * joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")} * ) */ private $groups; // ... public function __construct() { $this->groups = new \Doctrine\Common\Collections\ArrayCollection(); } } /** @Entity */ class Group { // ... } ~~~ 它是通过users_group的关系建立了二者之间的关系 8 多对多 可逆 Many-To-Many, Bidirectional ~~~ <?php /** @Entity */ class User { // ... /** * Many Users have Many Groups. * @ManyToMany(targetEntity="Group", inversedBy="users") * @JoinTable(name="users_groups") */ private $groups; public function __construct() { $this->groups = new \Doctrine\Common\Collections\ArrayCollection(); } // ... } /** @Entity */ class Group { // ... /** * Many Groups have Many Users. * @ManyToMany(targetEntity="User", mappedBy="groups") */ private $users; public function __construct() { $this->users = new \Doctrine\Common\Collections\ArrayCollection(); } // ... } ~~~ 9 Owning and Inverse Side on a ManyToMany association¶ ~~~ <?php class Article { private $tags; public function addTag(Tag $tag) { $tag->addArticle($this); // synchronously updating inverse side $this->tags[] = $tag; } } class Tag { private $articles; public function addArticle(Article $article) { $this->articles[] = $article; } } <?php $article = new Article(); $article->addTag($tagA); $article->addTag($tagB); ~~~ 10 多对多关系 自关联 Many-To-Many, Self-referencing 表结构: ~~~ CREATE TABLE User ( id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB; CREATE TABLE friends ( user_id INT NOT NULL, friend_user_id INT NOT NULL, PRIMARY KEY(user_id, friend_user_id) ) ENGINE = InnoDB; ALTER TABLE friends ADD FOREIGN KEY (user_id) REFERENCES User(id); ALTER TABLE friends ADD FOREIGN KEY (friend_user_id) REFERENCES User(id); ~~~ 以下的entity ~~~ <?php /** @Entity */ class User { // ... /** * Many Users have Many Users. * @ManyToMany(targetEntity="User", mappedBy="myFriends") */ private $friendsWithMe; /** * Many Users have many Users. * @ManyToMany(targetEntity="User", inversedBy="friendsWithMe") * @JoinTable(name="friends", * joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="friend_user_id", referencedColumnName="id")} * ) */ private $myFriends; public function __construct() { $this->friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection(); $this->myFriends = new \Doctrine\Common\Collections\ArrayCollection(); } // ... } ~~~ 1.Entity:Category use Doctrine\Common\Collections\ArrayCollection; class Category { // ... /** * @ORM\OneToMany(targetEntity="Product", mappedBy="category") */ protected $products; public function __construct() { $this->products = new ArrayCollection(); } } 2.Entity:Product class Product { // ... /** * @ORM\ManyToOne(targetEntity="Category", inversedBy="products") * @ORM\JoinColumn(name="category_id", referencedColumnName="id") */ protected $category; } 这样Category和Product就构成了1对多的映射。 php app/console doctrine:schema:update --force 3.、insert数据入库实例(保存相互关联的Entities) use AppBundle\Entity\Category; use AppBundle\Entity\Product; use Symfony\Component\HttpFoundation\Response; class DefaultController extends Controller { public function createProductAction() { $category = new Category(); $category->setName('Main Products'); $product = new Product(); $product->setName('Foo'); $product->setPrice(19.99); $product->setDescription('Lorem ipsum dolor'); // relate this product to the category $product->setCategory($category); $em = $this->getDoctrine()->getManager(); $em->persist($category); $em->persist($product); $em->flush(); return new Response( 'Created product id: '.$product->getId() .' and category id: '.$category->getId() ); } } 4.获取关联的对象 public function showAction($id) { $product = $this->getDoctrine() ->getRepository('AppBundle:Product') ->find($id); $categoryName = $product->getCategory()->getName(); } 5.另外一种查询方法 public function showProductsAction($id) { $category = $this->getDoctrine() ->getRepository('AppBundle:Category') ->find($id); $products = $category->getProducts(); } 6.还可以这么做 $product = $this->getDoctrine() ->getRepository('AppBundle:Product') ->find($id); $category = $product->getCategory(); // prints "Proxies\AppBundleEntityCategoryProxy" echo get_class($category); 7.关联记录(Repository的查询) // src/AppBundle/Entity/ProductRepository.php public function findOneByIdJoinedToCategory($id) { $query = $this->getEntityManager() ->createQuery( 'SELECT p, c FROM AppBundle:Product p JOIN p.category c WHERE p.id = :id' )->setParameter('id', $id); try { return $query->getSingleResult(); } catch (\Doctrine\ORM\NoResultException $e) { return null; } } public function showAction($id) { $product = $this->getDoctrine() ->getRepository('AppBundle:Product') ->findOneByIdJoinedToCategory($id); $category = $product->getCategory(); // ... }