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 属性。
首页
文章
动态
技术
Doctrine 2.* 字段类型参考
Haiqing7月 14, 2021
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: entity
manyToMany:
phonenumbers:
targetEntity: Phonenumber
joinTable:
name: users_phonenumbers
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
phonenumber_id:
referencedColumnName: id
unique: 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: Prop
fetch: LAZY
mappedBy: propName
orphanRemoval: true
cascade:
- persist
- remove
manyToMany:
categorys:
targetEntity: ShopBundle\Entity\Category
mappedBy: null
inversedBy: propNames
orphanRemoval: false
cascade:
- 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,因此性能更好。