mralston/laravel-eav

实现实体-属性-值模式,以补充Eloquent的自定义属性。

v1.0.2 2024-04-24 10:17 UTC

This package is auto-updated.

Last update: 2024-09-24 11:08:09 UTC


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存储。它提供了 getsetunset 方法

$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许可许可。