Doctrine 2.* 字段类型参考

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,因此性能更好。

发表评论