glhd / special
Requires
- php: >= 8.1
- ext-json: *
- illuminate/database: ^8|^9|^10|^11|12.x-dev|dev-master
- illuminate/support: ^8|^9|^10|^11|12.x-dev|dev-master
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- mockery/mockery: ^1.3
- orchestra/testbench: ^6.30|^7.27|^8.6|^9|9.x-dev
- phpunit/phpunit: ^9.5|^10.5
README
Special✨
有时候,某些数据库记录确实是 特殊的✨,你需要在代码中引用它们。
你可能有一些特殊的供应商,他们在一些特殊的地方有特殊处理,也许他们还会运行一些特殊的 artisan 命令。
special✨ 允许你使用 支持枚举 来引用 Eloquent 模型。与其用字符串或整数作为枚举的后台,不如将其视为使用数据库记录作为后台。
如果记录缺失,你可以让 special✨ 自动为你创建它。这在测试中尤其有用,你可能需要一些特殊的记录来执行一些特殊的测试,但你不想在设置时跟踪哪些测试需要运行特殊的种子器。
安装
composer require glhd/special
用法
首先,创建一个新的枚举并使用此包提供的 EloquentBacking
特性。
你可以 可选地 将 CreateWith
属性添加到任何枚举情况中,如果它缺失,special✨ 将使用这些值自动为您创建模型记录。
use Glhd\Special\EloquentBacking; enum SpecialOrganizations: string { use EloquentBacking; #[CreateWith(['name' => 'Laravel', 'url' => 'https://laravel.net.cn/'])] case Laravel = 'laravel'; #[CreateWith(['name' => 'Spatie', 'url' => 'https://spatie.be/'])] case Spatie = 'spatie'; #[CreateWith(['name' => 'Thunk', 'url' => 'http://thunk.dev/'])] case Thunk = 'kathunk'; // If your enum name is the same as the model name, this is optional. public static function modelClass(): string { return Organization::class; } }
现在,您可以使用这些枚举来访问支持模型。默认情况下,字符串被认为是 slug
列,整数被认为是 id
列,但这可以在项目级别或单个枚举级别进行配置。
SpecialOrganizations::Laravel->toArray(); // [ // 'id' => 1337, // 'slug' => 'laravel', // 'name' => 'Laravel', // 'url' => 'https://laravel.net.cn/', // 'created_at' => [...], // 'updated_at' => [...], // ]
Special 枚举装饰了底层模型,因此您通常可以像调用模型本身一样调用枚举。但有时您需要实际的模型实例副本,您可以使用
// Get a copy of the model — only loads from DB once, but clones each time SpecialOrganizations::Laravel->get(); // Get a single, shared copy — same instance each time SpecialOrganizations::Laravel->singleton(); // Get a fresh copy — always loads from the DB SpecialOrganizations::Laravel->fresh();
使用主键缓存
通常,您只需要特殊枚举来在另一个查询中使用其主键或设置关系。Special✨ 会缓存最近使用的 50 个主键,因此在许多情况下,您不需要进行单个数据库查询。您可以通过发布包配置来配置缓存的键数和缓存 TTL。
PullRequest::create([ 'organization_id' => SpecialOrganizations::Laravel->getKey(), 'ref_number' => 47785, 'title' => '[10.x] Add Collection::enforce() method', ]);
只要在过去的 1 小时内使用了 SpecialOrganizations::Laravel
,就可以设置 'organization_id'
值,而无需对数据库进行任何查询。
由于这些枚举的性质,这通常相当安全,因为它们使用的记录类型不太可能在您的应用程序中更改。话虽如此,您始终可以使用 php artisan cache:clear-special-keys
在任何时候清除缓存。
与 Laravel 关系一起使用
很多时候,您想使用特殊枚举来查找相关模型。我们提供了一些方便的方法来做这件事
PullRequests::query() ->forSpecial(SpecialOrganizations::Laravel) ->dumpRawSql(); // select * // from `pull_requests` // where `organization_id` = 1337
或者,您可以使用特殊枚举来约束现有查询。可以使用以下方式生成完全相同的查询
SpecialOrganizations::Laravel ->constrain(PullRequests::query()) ->dumpRawSql();
方法 constrain()
(以及 forSpecial
宏)都使用底层的主键缓存。这意味着大多数使用特殊枚举的关联查询都不会触发任何额外的数据库查询。
自动模型观察
Special✨ 会自动为任何您检索的模型注册模型观察器。这意味着如果您在请求期间更新或删除特殊模型,随后的枚举调用将自动反映这些更改。
这适用于使用包检索的更新模型。
// Get a copy of the Laravel organization, which causes it to be // cached for the rest of the request. $laravel = SpecialOrganizations::Laravel->singleton(); assert($laravel->name === 'Laravel'); // Now we'll update it without using our enum $org = Organizations::where('slug', 'laravel')->first(); $org->update(['name' => 'Laravel LLC']); // Later calls to the enum will reflect the changes $laravel = SpecialOrganizations::Laravel->singleton(); assert($laravel->name === 'Laravel LLC');