mralston / laravel-eav
实现实体-属性-值模式,以补充Eloquent的自定义属性。
Requires
- php: ^8.0
- illuminate/database: ^10.0
- illuminate/support: ^10.0
README
介绍
Laravel的实体属性值包。
来自 维基百科 的EAV定义
实体-属性-值模型(EAV)是一种数据模型,以高效的方式编码实体,其中可以用来描述实体的属性(属性、参数)数量可能很大,但实际上应用到给定实体的属性数量相对较小。
TL;DR 此包允许您在模型上处理未在底层数据库模式中定义的属性。
但为什么呢?
你们的科学家们太专注于他们是否能够做到,以至于没有停下来想他们是否应该这样做。
—— 伊恩·马尔科姆博士(杰夫·高布伦),侏罗纪公园
- 是的,已经有其他包提供了类似的功能。
- 是的,EAV有时因为性能问题被认为是一种反模式。
- 是的,这可能会被认为是重新发明非关系型数据库的轮子。
- 是的,我不管这些。🤷♂️
说实话,这最初是基于我有一个想法的验证性项目,旨在改善我参与维护的几个项目中一个混乱的现有实现。
我看到的EAV实现中,每个EAV属性都有一个独立的数据库记录。我认为大部分性能问题都来自于由此产生的大量额外的数据库流量。
我的概念是将所有EAV数据放入单个数据库记录的JSON字段中,每次模型实例只需要获取一次。
使用JSON字段的灵感来自 JSON字段 的 PlanetScale 的 Aaron Francis,所以向他致敬。也要感谢Aaron,当涉及到“你应该只用一个非关系型数据库”的论点时,他给了我们一张免罪卡。
安装
使用Composer安装此包
composer require mralston/laravel-eav
配置
此包没有配置,它不需要。太好了!
迁移
安装后,您需要迁移包的单个数据库表。
php artisan migrate
使用方法
此包旨在完全透明。您可以像平常一样读取和写入模型属性。
任何您想使用EAV的模型都需要使用 HasEntityAttributeValues
特性
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Mralston\Eav\Traits\HasEntityAttributeValues; class MyModel extends Model { use HasEntityAttributeValues; ... }
然后,您只需像平常一样在模型上设置属性
$myModel->myField = 'test'; dump($myModel->myField); // test
如果您设置的属性在底层表中定义为字段,它将像往常一样存储在那里。否则,它将作为EAV属性存储。
还有其他方法也可以访问EAV数据。
当传递可选的 $value
参数时,eav
方法作为组合访问器和修改器运行。
$myModel->eav('myField', 'test'); dump($myModel->eav('myField')); // test
可以使用 entityAttributeStore
关系访问底层的EAV存储。它提供了 get
、set
和 unset
方法
$myModel->entityAttributeStore->set('myField', 'test'); $myModel->entityAttributeStore->get('myField'); // test $myModel->entityAttributeStore->unset('myField'); $myModel->entityAttributeStore->get('myField'); // null
关于持久性的说明
EAV数据在保存关联模型时持久化到数据库。在此之前,您所做的任何更改都仅存在于内存中的模型上 - 就像标准的Eloquent属性一样。
// Load model from database and set an EAV attribute $myModel = MyModel::find(1); $myModel->myField = 'test'; dump($myModel->myField); // test // Load a second copy of the model and attempt to // retrieve the same EAV attribute. // It fails because it hasn't been saved yet $myModel2 = MyModel::find(1); dump($myModel2->myField); // null // Save the first model and its EAV attributes $myModel->save(); // Load another copy of the model from the database. // This one will have the EAV data $myModel3 = MyModel::find(1); dump($myModel3->myField); // test
同样地,如果你实例化了同一数据库记录的多个单独模型,每个模型实例都将拥有自己独特的EAV属性副本。你可以在一个模型实例上修改EAV属性,而其他实例将不受影响——就像标准的Eloquent属性一样。
$myModel = MyModel::find(1); $myModel->myField = 'foo'; $myModel2 = MyModel::find(1); $myModel->myField = 'bar'; dump($myModel->myField); // foo dump($myModel2->myField); // bar
安全漏洞
请直接通过电子邮件将安全漏洞发送给我:matt@mralston.co.uk。
许可
PDF是开源软件,受MIT许可许可。