Parental 是一个 Laravel 包 紧缩 它为 Eloquent 引入了单表继承 (STI) 功能。Parental 允许您使用子类扩展父模型,而无需为每个模型变体创建单独的数据库表,所有子类共享同一张表,并通过 type 列来区分它们。
使用案例
当模型拥有大部分相同属性但行为不同时,单表继承非常有用。常见示例包括:
- 用户类型
- 一个
Admin和一个Guest延伸基座User每个模型都有其自身的方法和关系 - 内容类型
- A
TextPost和ImagePost延伸Post模型,具有特定类型的关系,例如提及或附件 - 秩序状态
- A
PendingOrder和ShippedOrder扩展Order其中状态转换会改变模型类型
入门
通过 Composer 安装软件包:
作曲家
要求
tightco/parental
接下来,通过添加以下内容来定义父模型和子模型:
HasChildren
特征与父模型和
HasParent
每个子模型都有一个特性。每个子类都继承自父类,并且都从同一个数据库表中读取和写入数据:
使用
照亮\数据库\雄辩\模型
;使用
收起\家长\有孩子
;班级
命令
延伸
模型{
使用
有孩子
;}
使用
收紧\家长\有家长
;班级
待处理订单
延伸
命令{
使用
HasParent
;}
使用
收紧\家长\有家长
;班级
已发货订单
延伸
命令{
使用
HasParent
;}
当你创建一个
PendingOrder
或者
ShippedOrder
记录存储在
orders
一张桌子
type
设置列以标识子类。
自定义类型列
如果您的表使用除以下列名之外的列名:
type
用以下方式覆盖它
$childColumn
父模型上的属性:
班级
命令
延伸
模型{
使用
有孩子
;
受保护
子列
=
'地位'
;}
自定义类型别名
默认情况下,Parental 会将完全限定类名存储在 type 列中。您可以使用以下方式映射较短的别名:
$childTypes
父模型上的属性:
使用
照亮\数据库\雄辩\模型
;使用
收起\家长\有孩子
;班级
命令
延伸
模型{
使用
有孩子
;
受保护
子类型
=
[
'待办的'
=>
待处理订单
::班级
,
已发货
=>
已发货订单
::班级
,];}
这家商店
pending
或者
shipped
在数据库中,可以使用类型列代替完整的类名。如果您更喜欢使用数字标识符,类型列也支持整数值:
受保护
子类型
=
[
1
=>
待处理订单
::班级
,
2
=>
已发货订单
::班级
,];
类型之间的转换
become()
这
become()
该方法允许您在运行时将模型从一种子类型切换到另一种子类型。例如,当订单经历其生命周期时,您可以将其重新转换为不同的类:
$订单
=
待处理订单
::
查找或失败
(
1
(英文):$订单
=
$订单
->
变得
(
已发货订单
::班级
(英文):$订单
->
节省
();
该调用返回目标类的一个全新实例,并保留所有原始属性。Parental 还会分发一个
becoming
在切换之前发生事件,因此您可以监听类型更改并在发生更改时运行额外的逻辑。
急切地加载儿童特定关系
当查询返回多种子类型时,您可能需要加载仅存在于某些类上的关系。调用标准
load()
如果关系仅定义在一个子类型上,则会抛出错误。Parental 提供了专门的辅助函数来处理这种情况,方法是将 eager load 的范围限定到正确的子类:
$订单
->
加载子项
([
待处理订单
::班级
=>
[
'项目'
],
已发货订单
::班级
=>
[
“货物”
],]);
这些辅助函数适用于 Eloquent 查询构建器、集合和分页器:
// 关于查询命令
::
孩子们与
([
待处理订单
::班级
=>
[
'项目'
],
已发货订单
::班级
=>
[
“货物”
],])
->
得到
();// 计算子项之间的关系命令
::
childrenWithCount
([
待处理订单
::班级
=>
[
'项目'
],
已发货订单
::班级
=>
[
“货物”
],])
->
得到
();
要了解更多关于 Parental 的信息并查看源代码,请访问 GitHub 存储库 。





