Doctrine 2.* 字段类型参考转载

June 16, 2020
-
144
版本:Doctrine 2.* 常用YML的格式配置

Doctrine 2.* 的官方文档已有详细的说明,本文只是根据个人习惯对文档进行整理。

基本映射

简单例子(YML):

Message: 
type: entity
fields:
id:
type: integer
text:
length: 140
postedAt:
type: datetime
column: posted_at

字段属性映射类型(Property Mapping):

解释器根据字段属性的参数将其属性映射到数据库表中对应的列。

  • type:(可选,默认为“String”)用于列的映射类型。
  • name:(可选,默认为字段名称)数据库中的列名称。
  • length:(可选,默认为255)数据库中列的长度。(仅在使用字符串值的列时适用)。
  • unique:(可选,默认为FALSE)该列是否为唯一键。
  • nullable:(可选,默认为FALSE)数据库列是否可为空。
  • precision:(可选,默认为0)十进制(精确数字)列的精度(仅适用于十进制列),这是为值存储的最大位数。
  • scale:(可选,默认为0)十进制(精确数字)列的标度(仅适用于十进制列),代表小数点右边的位数,并且不得大于precision。
  • columnDefinition:(可选)允许定义用于创建列的自定义DDL代码段。警告:这通常会使SchemaTool混淆,总是将列检测为已更改。
  • options:(可选)生成DDL语句时传递给基础数据库平台的选项的键值对。

字段映射类型 (Doctrine Mapping Types):

字段属性 type 可选的映射类型。

  • string:将SQL VARCHAR映射到PHP字符串的类型。
  • integer:将SQL INT映射到PHP整数的类型。
  • smallint:将数据库SMALLINT映射到PHP整数的类型。
  • bigint:将数据库BIGINT映射到PHP字符串的类型。
  • boolean:将SQL布尔值或等效值(TINYINT)映射到PHP布尔值的类型。
  • decimal:将SQL DECIMAL映射到PHP字符串的类型。
  • date:将SQL DATETIME映射到PHP DateTime对象的类型。
  • time:将SQL TIME映射到PHP DateTime对象的类型。
  • datetime:将SQL DATETIME / TIMESTAMP映射到PHP DateTime对象的类型。
  • datetimetz:将SQL DATETIME / TIMESTAMP映射到带有时区的PHP DateTime对象的类型。
  • text:将SQL CLOB映射到PHP字符串的类型。
  • object:使用serialize()和将SQL CLOB映射到PHP对象的类型 unserialize()
  • array:使用serialize()和将SQL CLOB映射到PHP数组的类型 unserialize()
  • simple_array:使用implode()和将SQL CLOB映射到PHP数组的类型 explode(),并以逗号作为分隔符。重要信息 仅在确定您的值不能包含“,”时才使用此类型。
  • json_array:使用json_encode()和将SQL CLOB映射到PHP数组的类型 json_decode()
  • float:将SQL Float(Double Precision)映射到PHP double的类型。重要说明:仅适用于使用小数点作为分隔符的语言环境设置。
  • guid:将数据库GUID / UUID映射到PHP字符串的类型。默认为varchar,但如果平台支持,则使用特定类型。
  • blob:将SQL BLOB映射到PHP资源流的类型

主键

Message:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
fields:# fields here

关系映射

Doctrine 中把表的关联关系配置分为一对多、多对一和一对一三种类型:

一对多: 一个当前实体的实例有很多实例(引用)的refered实体。

多对一: 当前实体的许多情况下指的是refered实体的一个实例。

一对一: 当前实体的一个实例是指refered实体的一个实例。

关系映射字段类型:

JoinColumn:当前表和关联表的关联字段关系,name 当前表中的关联字段名(外键) ,referencedColumnName 被关联表中的字段名。

mappedBy:必须在(双向)关联的反向侧指定

inversedBy:必须在(双向)关联的所有方指定,会生成外键


一对一

单向关系: Shipment 关联到 Product 表,Product 中增加 shipment_id 字段(外键)并关联到 Shipment 表的 id 列。

Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id

生成的SQL结构

CREATE TABLE Product (
id INT AUTO_INCREMENT NOT NULL,
shipment_id INT DEFAULT NULL,
UNIQUE INDEX UNIQ_6FBC94267FE4B2B (shipment_id),
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE Shipment (
id INT AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Product ADD FOREIGN KEY (shipment_id) REFERENCES Shipment(id);

双向关系:

Customer:
oneToOne:
cart:
targetEntity: Cart
mappedBy: customer
Cart:
oneToOne:
customer:
targetEntity: Customer
inversedBy: cart
joinColumn:
name: customer_id
referencedColumnName: id

我们必须要在其上放置边的选择inversedBy属性。因为它是在Cart,这是关系的拥有方,从而保持外键。

生成的SQL结构

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);

一对多

双向关系:除联接表外一对多关联必须是双向的。这是因为一对多关联中的“Many”方拥有外键,使其成为拥有方。

这种双向映射需要在“One”上具有 mappedBy 属性,而在“Many”侧上需要 inversedBy 属性。

Product:
type: entity
oneToMany:
features:
targetEntity: Feature
mappedBy: product
Feature:
type: entity
manyToOne:
product:
targetEntity: Product
inversedBy: features
joinColumn:
name: product_id
referencedColumnName: id

生成的SQL结构

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);

单向连接表:单向的一对多关联可以通过连接表映射。从主义的角度来看,它是简单地映射为一个单向多到很多,其中上的连接列一个唯一约束强制执行一到多的基数。

User:type: entitymanyToMany:phonenumbers:targetEntity: PhonenumberjoinTable:name: users_phonenumbersjoinColumns:user_id:referencedColumnName: idinverseJoinColumns:phonenumber_id:referencedColumnName: idunique: true

生成的SQL结构

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);

自引用:比如有层级关系的分类等数据

Category:
type: entity
oneToMany:
children:
targetEntity: Category
mappedBy: parent
manyToOne:
parent:
targetEntity: Category
inversedBy: children

生成的SQL结构

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);

多对多

单向关系:用户和组实体之间的单向关联

User:
type: entity
manyToMany:
groups:
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id

生成的SQL结构

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);

双向关系

User:
type: entity
manyToMany:
groups:
targetEntity: Group
inversedBy: users
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id

Group:
type: entity
manyToMany:
users:
targetEntity: User
mappedBy: groups


在 @JoinColumn 和 @JoinTable 定义通常是可选的,并且具有合理的默认值。用于默认值以一对一的/多到一个关联如下连接列:

name: "_id"
referencedColumnName: "id"
#例如
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
#等同于
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id



关联删除


示例:

ShopBundle\Entity\PropName:
fields:
oneToMany:
props:targetEntity: Propfetch: LAZYmappedBy: propNameorphanRemoval: truecascade:- persist
 - remove
manyToMany:categorys:targetEntity: ShopBundle\Entity\CategorymappedBy: nullinversedBy: propNames
 orphanRemoval: falsecascade:
- persist- remove


cascade={“remove”}

在ORM体系下实现,在OneToMany或ManyToMany关系中使用。

如果实体PropName包含实体Prop,删除实体PropName,Doctrine也会删除collection中的所有Prop实体。

当PropName与Prop的级联集合很大时,在级联删除中需要很大的内存开销。

比如:你的User有一对多的关系Comment。如果你正在使用cascade=”remove”,您可以从一个User,删除关联的Comment。也可以在之后将Comment附到另一个User上。当你persist他们时,他们将被正确保存。

orphanRemoval=true

在ORM体系下实现,可以用在 OneToOne、 OneToMany 或 ManyToMany 中。与 cascade={"remove"} 的功能类似,实现方式不同。

如果实体PropName包含对私有实体Prop的引用,那么如果从Prop中删除引用PropName,则该实体Prop也应被删除,因为它不再被使用。

使用 orphanRemoval=true 选项时要注意被关联的对象是否与其它对象有关联,Doctrine 默认被关联对象是私有的,在最终持久化时删除关联数据。


比如:你的User有一对多的关系Comment。如果你正在使用 cascade=”remove”,您可以从一个User,删除关联的Comment,然后附上Comment到另一个User。当你persist他们时,他们将被正确保存。

但是如果您正在使用 orphanRemoval=true,即使您从一个User中的删除Comment,然后将其附加到另一个User,此Comment最终还是会在持久化期间被删除,因为该关联已被删除。

ondelete=”CASCADE”

由数据库自身管理

这将 “在数据库中”,把 On Delete Cascade(层叠删除) 这一属性,添加到外键所在的字段中。

本策略在运用时有些技巧,但它非常强力且快速。(引自 doctrine官方文档 )

比较前两种方式,ORM 做更少的事,因此性能占优。其删除动作由数据库服务器来完成,而不是通过 Doctrine,因此性能更好。