darkghosthunter/laraconfig

该软件包已被废弃且不再维护。未建议替代软件包。

Laravel 的按用户设置仓库系统

v1.3.5 2021-07-28 18:06 UTC

This package is auto-updated.

Last update: 2022-02-17 17:34:32 UTC


README

该软件包已被存档。

抱歉大家,我承担了太多,目前没有使用这个软件包来证明其支持。

我可能在不久的将来重新考虑这一点。

Xavier von Erlach - Unsplash #ooR1jY2yFr4

Latest Version on Packagist License Coverage Status Laravel Octane Compatible

Laraconfig

Laravel 的按用户设置仓库系统。

此软件包允许用户轻松快速地查询、更改和更新设置。

User::find(1)->settings->set('color', 'red');

要求

  • Laravel 8.x
  • PHP 8.0 或更高版本

工作原理

Laraconfig 通过扩展 Laravel 关系并包含迁移系统来管理它们。

每个设置只是一个值,它引用一个包含类型和名称等信息并链接到用户的父 "元数据"。

由于 Laraconfig 在幕后使用 Eloquent ORM,因此获取一个或所有设置的获取对开发者来说完全透明。

快速入门

您可以通过 composer 安装此软件包。

composer require darkghosthunter/laraconfig

首先,发布并运行迁移。这些将添加两个名为 user_settingsuser_settings_metadata 的表。一个存储每个用户的值,另一个存储设置的元数据。

php artisan vendor:publish --provider="DarkGhostHunter\Laraconfig\LaraconfigServiceProvider" --tag="migrations"
php artisan migrate

迁移使用一个形态列来连接到用户。您可以在迁移之前更改它。

其次,将 HasConfig 特性添加到您希望具有设置的 User 模型中。

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use DarkGhostHunter\Laraconfig\HasConfig;

class User extends Authenticatable
{
    use HasConfig;
    
    // ...
}

最后,使用 settings:publish artisan 命令。这将创建一个位于项目根目录中的 settings 文件夹和一个 users.php 文件。

php artisan settings:publish

现在,让我们创建一些设置。

设置清单

Laraconfig 通过一种类似清单的 settings/users.php 文件来管理全局用户设置。您将看到已经编写的示例设置。

use DarkGhostHunter\Laraconfig\Facades\Setting;

Setting::name('color')->string();

创建设置

要创建设置,请使用 Setting 门面。您可以从设置名称开始,该名称必须是唯一的,然后声明类型。

use DarkGhostHunter\Laraconfig\Facades\Setting;

Setting::name('dark_mode')->boolean();

Laraconfig 与 7 种类型的设置兼容,反映了它们的 PHP 本地类型,以及 Collection 和 Datetime(Carbon)对象。

  • array()
  • boolean()
  • collection()
  • datetime()
  • float()
  • integer()
  • string()

数组和集合在数据库中作为 JSON 序列化。

默认值

所有设置都默认为 null,但您可以使用 default() 方法设置不同的初始值。

use DarkGhostHunter\Laraconfig\Facades\Setting;

Setting::name('color')->string()->default('black');

您可以使用 setDefault() 将值还原到默认值。

启用或禁用

默认情况下,所有设置都默认启用,但您可以使用disabled()来更改此设置。

Setting::name('color')->disabled();

启用或禁用是表示性的;禁用的设置仍然可以更新。您可以使用setIfEnabled()来程序化地设置值。

分组设置

您可以为设置设置一个组名。当您希望在前端按顺序显示设置并通过分组来分离它们时,这可能很有用。

Setting::name('color')->group('theme');

当Laraconfig迁移新的设置时,这些设置会创建到所有模型中。您可以通过“包”来过滤一组设置。

默认情况下,所有设置都在users包下创建,但您可以使用bag()方法更改任何内容的默认包。

Setting::name('color')->group('theme')->bag('style');

Setting::name('notify_email')->boolean()->default(true)->bag('notifications');
Setting::name('notify_sms')->boolean()->default(false)->bag('notifications');

稍后,在您的模型中,您可以使用filterBags()过滤您想要与之交互的包。

迁移设置

创建完设置后,您应该使用settings:migrate让Laraconfig将设置元数据添加到您的数据库中。

php artisan settings:migrate

在幕后,Laraconfig会查看您的模型,以查找使用HasConfig特质的模型,并根据清单上的信息相应地填充设置。

迁移只执行正向。一旦执行完成,就无法回滚迁移。在生产环境中,删除设置需要确认。

添加新设置

只需创建一个新的设置并运行settings:migrate即可。现有的设置不会再次创建,因为Laraconfig会在执行之前检查它们的存在。

use DarkGhostHunter\Laraconfig\Facades\Setting;

Setting::name('color')->string()->default('black');

// This new setting will be created 
Setting::name('notifications')->boolean()->default(true);

删除旧设置

要删除旧设置,只需删除它们的声明并运行settings:migrate。Laraconfig将比较声明的设置和数据库中创建的设置,并在迁移执行结束时删除那些在清单中不再存在的设置。

use DarkGhostHunter\Laraconfig\Facades\Setting;

// Commenting this line will remove the "color" setting on migration.
// Setting::name('color')->string()->default('black');

// This new setting will be created 
Setting::name('notifications')->boolean()->default(true);

由于此过程可能很危险,生产环境需要确认

升级设置

您不需要直接进入数据库来更新设置。相反,只需在清单中直接更改设置属性。Laraconfig将相应地更新元数据。

假设我们有一个“颜色”设置,我们希望将其从字符串更新为颜色数组和默认值及组。

Setting::name('color')->string()->bag('theme');

// This is the new declaration.
// Setting::name('color')
//    ->array()
//    ->default(['black'])
//    ->group('theme');

Laraconfig将检测到新更改,并更新元数据,同时保持用户的值不变。

// This is the old declaration.
// Setting::name('color')->string()->bag('theme');

Setting::name('color')
    ->array()
    ->default(['black'])
    ->group('theme');

只有在迁移时间设置与之前不同时,才会执行更新。

完成操作后,我们可以使用settings:migrate将旧设置迁移到新设置。用户将保留他们之前相同的设置值,但如果…我们想要更改每个用户的值怎么办?我们可以使用using()方法将每个用户的设置传递到回调,该回调将返回新值。

Setting::name('color')
    ->array()
    ->default('black')
    ->group('theme')
    ->using(fn ($old) => $old->value ?? 'black'); // If the value is null, set it as "black".

只有当设置在迁移时间与之前不同时,using()方法才会运行。

在幕后,Laraconfig 会查找 "color" 设置,更新元数据,然后使用一个 lazy() 查询 来通过回调更新值。

如果您有数十万条记录,建议直接在数据库上迁移,因为这个过程比直接 SQL 语句更安全但更慢。

迁移到新设置

在其他情况下,您可能希望将设置迁移到完全新的设置。在两种情况下,您都可以使用 from() 来获取要迁移的旧设置值,如果您还想更新每个用户的值,可以使用 using()

以上述相同示例为例,我们将 "color" 设置迁移到简单的 "dark theme" 设置。

// This old declaration will be deleted after the migration ends.
// Setting::name('color')->string()->bag('theme');

// This is a new setting.
Setting::name('dark')
    ->boolean()
    ->default(false)
    ->group('theme')
    ->from('color')
    ->using(static fn ($old) => $old->value === 'black'); // If it's black, then it's dark.

只有当旧设置在迁移时存在时,fromusing 才会执行。

在幕后,Laraconfig 首先创建新的 "theme" 设置,然后在数据库中查找旧的 "color" 设置以将旧值转换为新值。由于旧设置不在配置文件中,它将从数据库中删除。

管理设置

Laraconfig 以类似于任何 Eloquent Morph-Many Relationship 的方式处理设置,但功能更强大。

只需在您的模型上使用 settings 属性。这个属性就像您的正常 Eloquent Collection,因此您可以访问所有工具。

$user = User::find(1);

echo "Your color is: {$user->settings->get('color')}.";

建议使用 settings,因为它只会加载一次设置。

初始化

默认情况下,HasConfig 特性会在通过 Eloquent ORM 成功创建用户后,在数据库中创建一个新的设置包,因此您不需要创建任何设置。

如果您想手动处理初始化,可以使用 shouldInitializeConfig() 方法并返回 false,这在程序化初始化设置时非常有用。

// app/Models/User.php

/**
 * Check if the user should initialize settings automatically after creation.
 * 
 * @return bool
 */
protected function shouldInitializeConfig(): bool
{
    // Don't initialize the settings if the user is not verified from the start.
    // We will initialize them only once the email is properly verified.
    return null !== $this->email_verified_at;
}

由于示例中的用户不会进行初始化,我们必须手动使用 initialize() 来执行它。

// Initialize if not initialized before.
$user->settings()->initialize();

// Forcefully initialize, even if already initialized.
$user->settings()->initialize(true);

检查设置初始化

您可以使用 isInitialized() 检查用户配置是否已初始化。

if ($user->settings()->isInitialized()) {
    return 'You have a config!';
}

检索设置

您可以使用名称轻松获取设置的值,这使得一切都变成了一个美丽的 单行代码

return "Your favorite color is {$user->settings->color}";

由于这仅支持字母数字和下划线字符,您可以使用 value()

return "Your favorite color is {$user->settings->value('color')}";

您还可以使用 get() 获取底层 Setting 模型。如果设置不存在,它将返回 null

$setting = $user->settings->get('theme');

echo "You're using the [$setting->value] theme.";

由于 settings 是一个 collection,您可以访问所有的好处,如迭代。

foreach ($user->settings as $setting) {
    echo "The [$setting->name] has the [$setting->value] value.";
}

您还可以使用 only() 方法通过名称返回设置集合,或使用 except() 获取除指定的设置之外的所有设置。

$user->settings->only('colors', 'is_dark');

$user->settings->except('dark_mode');

分组设置

由于设置列表是一个集合,您可以使用 groups() 方法按所属组的名称对它们进行分组。

$user->settings->groups(); // or ->groupBy('group')

请注意,设置默认情况下会被分组到 default 组(没有双关语)。

设置值

通过发出设置名称和值,可以轻松设置值。

$user->settings->color = 'red';

由于此功能仅支持由字母数字和下划线组成的设置名称,因此您还可以通过发出设置名称来使用 set() 方法设置值。

$user->settings->set('color-default', 'red');

或者,您可以直接在模型本身中进入纯粹模式。

$setting = $user->settings->get('color');

$setting->value = 'red';
$setting->save();

当使用 set() 一次设置多个设置时,可以使用数组,这在处理 验证返回的数组 时非常有用。

$user->settings->set([
    'color' => 'red',
    'dark_mode' => false,
]);

使用缓存 时,任何更改都会立即使缓存无效,并在垃圾回收之前排队生成。

但是,直接将设置更新到数据库中 不会重新生成缓存

默认设置

您可以使用设置实例上的 setDefault() 或使用 settings 属性,将设置还原到默认值。

$setting = $user->settings->get('color');

$setting->setDefault();

$user->settings->setDefault('color');

如果设置没有默认值,则将使用 null

检查是否为 null

使用 isNull() 和设置名称检查是否设置了 null 值。

if ($user->settings->isNull('color')) {
    return 'The color setting is not set.';
}

禁用/启用设置

出于展示目的,所有设置默认都是启用的。您可以使用 enable()disable() 分别启用或禁用设置。要检查设置是否启用,请使用 isEnabled() 方法。

$user->settings->enable('color');

$user->settings->disable('color');

即使禁用设置也可以设置它。如果您只想在启用时设置值,请使用 setIfEnabled()

$user->settings->setIfEnabled('color', 'red');

设置包

Laraconfig 使用一个名为 default 的单一包。如果您在清单中声明了不同的包集 您可以使用 filterBags() 方法创建一个仅使用特定包集的模型,该方法应返回包名称(或名称)。

// app/Models/User.php
i

上述方法将在从数据库检索设置时应用筛选器。这使得在用户具有不同的角色或属性或以编程方式时轻松交换包。

所有 设置都为具有 HasConfig 特性的所有模型创建,而不管模型使用的包是什么。

禁用包筛选器作用域

Laraconfig 对查询应用筛选器以排除不在模型包中的设置。虽然这简化了开发,但有时您将想要使用所有可用的设置集。

有两种方法可以禁用包筛选器。第一种方法相对简单:只需在查询时间使用 withoutGlobalScope() 即可,这将允许查询用户可用的所有设置。

use DarkGhostHunter\Laraconfig\Eloquent\Scopes\FilterBags;

$allSettings = $user->settings()->withoutGlobalScope(FilterBags::class)->get();

如果您想要一个更 永久 的解决方案,只需在模型中使用 filterBags() 方法时返回空数组或 null,这将完全禁用作用域。

/**
 * Returns the bags this model uses for settings.
 *
 * @return array|string
 */
public function filterBags(): array|string|null
{
    return null;
}

缓存

每次请求都击中数据库以检索用户设置可能会产生负面影响,如果您预计会经常发生这种情况。为了避免这种情况,您可以激活一个缓存,每次设置更改时都会重新生成。

缓存实现避免了数据竞争。它只为最后更改的数据重新生成缓存,所以如果有两个或更多进程尝试将某些内容保存到缓存中,只有最新的数据会被持久化。

启用缓存

您可以使用将 LARACONFIG_CACHE 环境变量设置为 true 的方式轻松启用缓存,并使用非默认缓存存储(如 Redis)的 LARACONFIG_STORE

LARACONFIG_CACHE=true
LARACONFIG_STORE=redis

或者,检查 laraconfig.php 文件以自定义缓存 TTL 和前缀。

管理缓存

您可以使用 regenerate() 强制重新生成单个用户的缓存。这基本上是将现有的设置保存到缓存中。

$user->settings->regenerate();

您还可以使用 invalidate() 使缓存的设置失效,这将仅从缓存中删除条目。

$user->settings->invalidate();

最后,您可以将 regeneratesOnExit 设置为 true 以获得一丝安心,这样当设置被 PHP 进程垃圾回收时,将会重新生成缓存。

$user->settings->regeneratesOnExit = true;

您可以在配置文件中禁用自动重新生成。

迁移时重新生成缓存

如果 缓存已激活,迁移将在完成后为每个用户使设置缓存失效。

根据缓存系统,忘记每个缓存键可能会产生负面影响。相反,您可以使用 --flush-cache 命令来刷新 Laraconfig 所使用的缓存存储,而不是逐个删除每个键。

php artisan settings:migrate --flush-cache

由于这将删除缓存的所有数据,建议为 Laraconfig 使用专用的缓存存储,如单独的 Redis 数据库。

验证

设置值将被 强制转换为 类型,但不会进行验证。您应该在应用程序中验证您计划存储在设置中的每个值。

use App\Models\User;
use Illuminate\Http\Request;

public function store(Request $request, User $user)
{
    $settings = $request->validate([
        'age' => 'required|numeric|min:14|max:100',
        'color' => 'required|string|in:red,green,blue'
    ]);
    
    $user->settings->setIfEnabled($settings);
    
    // ...
}

测试

最终,您将面临为每个创建的用户创建设置和元数据的问题。除非您已禁用 初始化,否则您可以在创建用户之前轻松地将元数据直接存储到数据库中。

public function test_user_has_settings(): void
{
    Metadata::forceCreate([
        'name'    => 'foo',
        'type'    => 'string',
        'default' => 'bar',
        'bag'     => 'users',
        'group'   => 'default',
    ]);
    
    $user = User::create([
        // ...
    ]);
        
    // ...
}

安全性

如果您发现任何与安全相关的问题,请通过电子邮件发送至 darkghosthunter@gmail.com,而不是使用问题跟踪器。

许可

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