mwakalingajohn / larasettings
为 Laravel 提供的针对用户设置的仓库系统,由 ricventu/larasettings 分支而来
Requires
- php: >=8.0
- illuminate/cache: ^10.0
- illuminate/collections: ^10.0
- illuminate/config: ^10.0
- illuminate/database: ^10.0
- illuminate/support: ^10.0
- symfony/console: ^6.0
Requires (Dev)
- mockery/mockery: ^1.5
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2024-09-19 02:52:05 UTC
README
此包是 ricventu/Laraconfig 的分支,我修复了一些问题,并更新了依赖项以用于 Laravel 10.x
要安装此仓库,请将以下内容添加到您的 composer.json 中,将 master
更改为您想要的分支
"repositories":[
{
"type": "vcs",
"url": "https://github.com/ricventu/LaraSettings.git"
}
],
"require": {
"mwakalingajohn/larasettings": "dev-master",
}
LaraSettings
Laravel 的用户设置仓库系统。
此包允许用户拥有可查询、更改甚至快速更新的设置。
User::find(1)->settings->set('color', 'red');
要求
- Laravel 10.x
如何使用
LaraSettings 通过扩展 Laravel 关系并包括迁移系统来工作,以便轻松管理它们。
每个设置只是一个值,它引用一个包含类型和名称等信息的父 "元数据",同时与用户关联。
由于 LaraSettings 在幕后使用 Eloquent ORM,因此获取一个或所有设置对开发人员来说是完全透明的。
快速入门
您可以通过 composer 安装此包。
composer require mwakalingajohn/larasettings
首先,发布并运行迁移。这将添加两个表,分别称为 user_settings
和 user_settings_metadata
。一个包含每个用户的值,另一个包含设置的元数据。
php artisan vendor:publish --provider="MwakalingaJohn\LaraSettings\LaraSettingsServiceProvider" --tag="migrations"
php artisan migrate
迁移使用一个形态列来连接到用户。您可以在迁移之前更改它。
其次,将 HasConfig
特性添加到您想要具有设置的 User 模型中。
namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use MwakalingaJohn\LaraSettings\HasConfig; class User extends Authenticatable { use HasConfig; // ... }
最后,使用 settings:publish
artisan 命令。这将创建一个位于项目根目录的 settings
文件夹和一个 users.php
文件。
php artisan settings:publish
现在,让我们创建一些设置。
设置清单
LaraSettings 通过一种类似 清单 的方式全局管理用户设置,即 settings/users.php
文件。您将看到已经编写好的示例设置。
use MwakalingaJohn\LaraSettings\Facades\Setting; Setting::name('color')->string();
创建设置
要创建设置,请使用 Setting
外观。您可以从设置名称开始,名称必须是唯一的,然后声明类型。
use MwakalingaJohn\LaraSettings\Facades\Setting; Setting::name('dark_mode')->boolean();
LaraSettings 与 7 种设置类型兼容,它们反映了 PHP 的原生类型,以及 Collection 和 Datetime (Carbon) 对象。
array()
boolean()
collection()
datetime()
float()
integer()
string()
数组和集合在数据库中以 JSON 格式序列化。
默认值
所有设置都有 null
的默认值,但您可以使用 default()
方法设置不同的初始值。
use MwakalingaJohn\LaraSettings\Facades\Setting; Setting::name('color')->string()->default('black');
您可以使用
setDefault()
将值恢复到默认值。
启用或禁用
默认情况下,所有设置都启用,但您可以使用 disabled()
改变此设置。
Setting::name('color')->disabled();
启用或禁用是表现性的;禁用的设置仍然可以更新。您可以使用
setIfEnabled()
编程设置值。
分组设置
您可以将组名设置到设置中。这很有用,当您希望在前端按顺序显示设置时,可以按 分组 分隔。
Setting::name('color')->group('theme');
包
当LaraSettings迁移新设置时,这些设置会被创建到所有模型中。您可以通过“包”来过滤特定的设置集。
默认情况下,所有设置都创建在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
让LaraSettings将设置元数据添加到您的数据库中。
php artisan settings:migrate
在幕后,LaraSettings会查找使用HasConfig
特质的模型,并根据清单上的信息相应地填充设置。
迁移仅正向运行。一旦完成,就无法撤销迁移。在生产环境中,删除设置需要确认。
添加新设置
只需创建一个新的设置并运行settings:migrate
。现有的设置不会再次创建,因为LaraSettings在执行之前会检查它们的存在。
use MwakalingaJohn\LaraSettings\Facades\Setting; Setting::name('color')->string()->default('black'); // This new setting will be created Setting::name('notifications')->boolean()->default(true);
删除旧设置
要删除旧设置,只需删除它们的声明并运行settings:migrate
。LaraSettings会将声明的设置与数据库中创建的设置进行比较,并在迁移执行结束时删除不再存在于清单中的设置。
use MwakalingaJohn\LaraSettings\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);
由于此过程可能很危险,生产环境需要确认。
升级设置
您无需直接进入数据库即可更新设置。相反,只需在清单中直接更改设置属性。LaraSettings将相应地更新元数据。
假设我们有一个“颜色”设置,我们希望将其从字符串更新为包含默认值和组的颜色数组。
Setting::name('color')->string()->bag('theme'); // This is the new declaration. // Setting::name('color') // ->array() // ->default(['black']) // ->group('theme');
LaraSettings将检测新更改,并更新元数据,同时保持用户值不变。
// 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()
方法仅在设置在迁移时间与之前不同时运行。
在幕后,LaraSettings将查找“颜色”设置,更新元数据,然后使用lazy()
查询通过回调更新值。
如果您有数十万条记录,请考虑直接在数据库上迁移,因为这个过程比直接SQL语句更安全但更慢。
迁移到新设置
在其他情况下,您可能希望将设置迁移到一个全新的设置。在这两种情况下,您都可以使用from()
来获取要迁移的旧设置值,如果您还想更新每个用户的值,可以使用using()
。
以相同的示例,我们将“颜色”设置迁移到简单的“深色主题”设置。
// 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.
from
和using
仅在迁移时间旧设置存在时执行。
在幕后,LaraSettings首先创建新的“主题”设置,然后在数据库中查找旧的“颜色”设置以将旧值转换为新值。由于旧设置不在清单中,它将被从数据库中删除。
管理设置
LaraSettings 处理设置,就像任何 Eloquent Morph-Many 关系 一样,但更加强大。
只需在您的模型上使用 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');
设置包
LaraSettings 使用一个名为 default
的单个包。如果您在清单中声明了不同的包集,则可以使用 filterBags()
方法创建一个模型,该模型仅使用特定的包集,该方法应返回包名称(或名称)。
// app/Models/User.php
i
以上操作会在从数据库获取设置时应用过滤器。这使得当用户具有不同的角色或属性,或以编程方式时,可以轻松地交换包。
所有设置都为所有具有
HasConfig
特性的模型创建,而不管模型使用的包是什么。
禁用包过滤器作用域
LaraSettings会对查询应用过滤器,以排除不在模型包中的设置。虽然这简化了开发,但有时您可能希望与可用的全部设置集一起工作。
有两种方法可以禁用包过滤器。第一种相对简单:只需在查询时使用withoutGlobalScope()
,这将允许查询用户可用的所有设置。
use MwakalingaJohn\LaraSettings\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; }
缓存
在每次请求中击中数据库以检索用户设置可能会对性能产生负面影响,如果您预计这种情况会发生很多。为了避免这种情况,您可以激活一个缓存,该缓存将在设置更改时重新生成。
缓存实现避免了数据竞争。它仅针对最后更改的数据重新生成缓存,因此如果两个或多个进程试图将内容保存到缓存中,只有最新的数据将被保留。
启用缓存
您可以通过将LARASETTINGS_CACHE
环境变量设置为true
轻松启用缓存,并使用LARASETTINGS_STORE
使用非默认缓存存储(如Redis)。
LARASETTINGS_CACHE=true LARASETTINGS_STORE=redis
或者,检查
larasettings.php
文件以自定义缓存TTL和前缀。
管理缓存
您可以使用regenerate()
强制重新生成单个用户的缓存。这基本上是保存现有的设置并将它们保存到缓存中。
$user->settings->regenerate();
您还可以使用invalidate()
使缓存的设置无效,这将简单地从缓存中删除条目。
$user->settings->invalidate();
最后,您可以通过将regeneratesOnExit
设置为true
来获得一丝安慰,这将使PHP进程在垃圾回收设置时重新生成缓存。
$user->settings->regeneratesOnExit = true;
您可以在配置文件中禁用自动重新生成。
在迁移时重新生成缓存
如果缓存已激活,迁移将在完成后为每个用户使设置缓存无效。
根据缓存系统,忘记每个缓存键可能会产生负面影响。相反,您可以使用--flush-cache
命令刷新LaraSettings使用的缓存存储,而不是逐个删除每个键。
php artisan settings:migrate --flush-cache
由于这将删除缓存中的所有数据,建议为LaraSettings使用一个专用的缓存存储,如单独的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([ // ... ]); // ... }
安全
如果您发现任何安全问题,请通过电子邮件mwakalingajohn@gmail.com而不是使用问题跟踪器。
许可
MIT许可(MIT)。有关更多信息,请参阅许可文件。