spatie/laravel-schemaless-attributes

为 Eloquent 模型添加无模式属性

2.5.0 2024-02-29 08:18 UTC

README

Latest Version on Packagist GitHub Workflow Status Total Downloads

你是否想在你的 Eloquent 中加入一些 NoSQL 的精神?这个包正是这样做的。它提供了一个特质,当应用于模型时,允许你在单个 JSON 列中存储任意值。

以下是一些示例。我们在这里使用的是 extra_attributes 列,但你可以将其命名为 你想要的任何名称

// add and retrieve an attribute
$yourModel->extra_attributes->name = 'value';
$yourModel->extra_attributes->name; // returns 'value'

// you can also use the array approach
$yourModel->extra_attributes['name'] = 'value';
$yourModel->extra_attributes['name'] // returns 'value'

// setting multiple values in one go
$yourModel->extra_attributes = [
   'rey' => ['side' => 'light'],
   'snoke' => ['side' => 'dark']
];

// setting/updating multiple values in one go via set()
$yourModel->extra_attributes->set([
   'han' => ['side' => 'light'],
   'snoke' => ['side' => 'dark']
]);

// retrieving values using dot notation
$yourModel->extra_attributes->get('rey.side'); // returns 'light'

// retrieve default value when attribute is not exists
$yourModel->extra_attributes->get('non_existing', 'default'); // returns 'default'

// it has a modelScope to retrieve all models with the given schemaless attributes
$yourModel->withSchemalessAttributes(['name' => 'value', 'name2' => 'value2'])->get();

// delete key & value
$yourModel->extra_attributes->forget('key');

支持我们

我们投入了大量资源来创建 一流的开源包。你可以通过 购买我们的付费产品之一 来支持我们。

我们非常感激你从家乡寄给我们明信片,提到你正在使用我们哪个包。你可以在 我们的联系页面 上找到我们的地址。我们将在 我们的虚拟明信片墙上 发布所有收到的明信片。

要求

此包需要一个支持 json 列的数据库,例如 MySQL 5.7 或更高版本。

安装

对于 Laravel 版本 6 & 7 或 PHP 7,请使用此包的 1.x 版本。

您可以通过 composer 安装此包

composer require spatie/laravel-schemaless-attributes

无模式属性将存储在您模型的表中的 json 列上。让我们添加该列并准备模型。

添加存储无模式属性的列

为所有你想添加无模式属性的模型添加迁移。你应该在 Blueprint 上使用 schemalessAttributes 方法来添加一个列。你给 schemalessAttributes 的参数是将要添加的列名。你可以使用你喜欢的任何名称。你也可以自由地向你的表添加任意数量的无模式属性列。在这个 README 的所有示例中,我们将使用一个名为 extra_attributes 的单列。

Schema::table('your_models', function (Blueprint $table) {
    $table->schemalessAttributes('extra_attributes');
});

准备模型

为了与无模式属性一起工作,你需要在你的模型上添加一个自定义转换和范围。以下是你需要添加的内容示例,如果你选择了 extra_attributes 作为你的列名。

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;

class TestModel extends Model
{
    // ...

    public $casts = [
        'extra_attributes' => SchemalessAttributes::class,
    ];

    public function scopeWithExtraAttributes(): Builder
    {
        return $this->extra_attributes->modelScope();
    }

    // ...
}

如果你需要在单个模型上支持多个无模式列,你应该使用 SchemalessAttributesTrait 特质。以下是你需要添加的内容示例,如果你选择了 extra_attributes, other_extra_attributes 作为你的列名。

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\SchemalessAttributes\SchemalessAttributes;
use Spatie\SchemalessAttributes\SchemalessAttributesTrait;

class TestModel extends Model
{
    use SchemalessAttributesTrait;

    // ...
    
    /**
     * @var array
     */
    protected $schemalessAttributes = [
        'extra_attributes',
        'other_extra_attributes',
    ];

    public function scopeWithExtraAttributes(): Builder
    {
        return $this->extra_attributes->modelScope();
    }
    
    public function scopeWithOtherExtraAttributes(): Builder
    {
        return $this->other_extra_attributes->modelScope();
    }

    // ...
}

如果你想在多个模型之间重用此行为,你可以选择将函数放入你自己的特质中。以下是一个这样的特质示例

namespace App\Models\Concerns;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;

trait HasSchemalessAttributes
{
    public function initializeHasSchemalessAttributes()
    {
        $this->casts['extra_attributes'] = SchemalessAttributes::class;
    }
    
    public function scopeWithExtraAttributes(): Builder
    {
        return $this->extra_attributes->modelScope();
    }
}

用法

获取和设置无模式属性

这是获取和设置无模式属性最简单的方式

$yourModel->extra_attributes->name = 'value';

$yourModel->extra_attributes->name; // Returns 'value'

或者,你可以使用数组方法

$yourModel->extra_attributes['name'] = 'value';

$yourModel->extra_attributes['name']; // Returns 'value'

你可以通过将数组赋值给它来替换所有现有的无模式属性。

// All existing schemaless attributes will be replaced
$yourModel->extra_attributes = ['name' => 'value'];
$yourModel->extra_attributes->all(); // Returns ['name' => 'value']

你也可以选择使用 getset 方法。这些方法支持点表示法。

$yourModel->extra_attributes = [
   'rey' => ['side' => 'light'],
   'snoke' => ['side' => 'dark'],
];
$yourModel->extra_attributes->set('rey.side', 'dark');

$yourModel->extra_attributes->get('rey.side'); // Returns 'dark

你还可以将默认值传递给 get 方法。

$yourModel->extra_attributes->get('non_existing', 'default'); // Returns 'default'

持久化无模式属性

要持久化无模式属性,就像处理普通属性一样,您应该在模型上调用 save() 方法。

$yourModel->save(); // Persists both normal and schemaless attributes

检索具有特定无模式属性的模型

以下是使用提供的 modelScope 的方法。

// Returns all models that have all the given schemaless attributes
$yourModel->withExtraAttributes(['name' => 'value', 'name2' => 'value2'])->get();

如果您只想搜索单个自定义属性,可以使用 modelScope 如下所示

// returns all models that have a schemaless attribute `name` set to `value`
$yourModel->withExtraAttributes('name', 'value')->get();

此外,如果您只想搜索具有自定义运算符的单个自定义属性,可以使用 modelScope 如下所示

// returns all models that have a schemaless attribute `name` starting with `value`
$yourModel->withExtraAttributes('name', 'LIKE', 'value%')->get();

如果您只想搜索嵌套自定义属性,可以使用 modelScope 如下所示

// returns all models that have a schemaless nested attribute `han.side` set to `light`
$yourModel->withExtraAttributes('han->side', 'light')->get();

测试

首先创建一个名为 laravel_schemaless_attributes 的 MySQL 数据库。然后您可以运行测试:

composer test

变更日志

有关最近更改的更多信息,请参阅 变更日志

贡献

有关详细信息,请参阅 贡献指南

安全漏洞

有关如何报告安全漏洞,请参阅 我们的安全策略

鸣谢

许可协议

MIT 许可协议 (MIT)。有关更多信息,请参阅 许可文件