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();
// ...
}