alajusticia / laravel-expirable
使 Eloquent 模型具有过期功能
Requires
- php: ^8.1
- illuminate/console: ^10.0|^11.0
- illuminate/database: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
- nesbot/carbon: ^2.67|^3.0
Requires (Dev)
- mockery/mockery: ^1.5
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^10.0
README
本包受 SoftDeletes 特性的启发,提供了一组让 Eloquent 模型支持过期的特性。
它依赖于一个额外的属性(默认命名为 expires_at
),该属性包含过期日期(或 null
以使模型永不过期)。
当达到过期日期时,模型将自动从所有 Eloquent 查询结果中消失(但仍保留在数据库中)。
兼容性
您正在阅读此包最新版本(v2)的文档。
安装
使用以下命令通过 composer 安装包
composer require alajusticia/laravel-expirable
您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="ALajusticia\Expirable\ExpirableServiceProvider"
准备你的模型
为了使模型支持过期,请添加本包提供的 Expirable 特性
use ALajusticia\Expirable\Traits\Expirable; use Illuminate\Database\Eloquent\Model; class Subscription extends Model { use Expirable;
此特性会自动将过期属性添加到需要转换为日期的属性列表中。
过期属性的默认名称
默认情况下,该包会在您的模型中添加一个名为 expires_at
的属性。您可以通过设置 EXPIRES_AT
常量来更改此名称(不要忘记在迁移中设置相同的列名,见下文)。
例如,假设我们有一个 Subscription
模型,我们希望属性名为 ends_at
use ALajusticia\Expirable\Traits\Expirable; use Illuminate\Database\Eloquent\Model; class Subscription extends Model { use Expirable; const EXPIRES_AT = 'ends_at';
您也可以通过在 expirable.php
配置文件中使用 attribute_name
选项全局更改所有可过期模型的属性名(常量具有优先级)。如果您在配置文件中全局更改了名称,则无需在迁移中设置名称,因为它将自动填充。
设置默认的有效期
您可以使用 defaultExpiresAt
公共静态方法设置默认的有效期。
此方法必须返回一个日期对象或 null
。这样,在保存模型时,除非您明确提供日期,否则会自动添加过期日期。
设置六个月默认有效期的示例
use ALajusticia\Expirable\Traits\Expirable; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; class Subscription extends Model { use Expirable; // ... public static function defaultExpiresAt() { return Carbon::now()->addMonths(6); }
// Create a new subscription which will expire in six months (using default expiration date) $subscription = new Subscription; $subscription->save(); // Create a new subscription which will expire in one year (overwrite the default expiration date) $subscription = new Subscription; $subscription->expiresAt(Carbon::now()->addYear()); $subscription->save();
准备你的迁移
该包要求您在迁移中添加可过期列。为了方便,该包提供了 expirable()
和 dropExpirable()
蓝图宏,可直接在迁移文件中使用。
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->expirable(); }); } /** * Reverse the migrations. * * @return void */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropExpirable(); }); } };
默认情况下,数据库列名(如模型属性)将是expires_at
或配置文件中的名称。如果您使用EXPIRES_AT
常量修改了模型上属性的默认名称,您需要在迁移中为列设置相同的自定义名称,通过给宏提供一个带有该名称的参数。
继续我们的订阅示例
public function up() { Schema::table('subscriptions', function (Blueprint $table) { $table->expirable('ends_at'); }); } public function down() { Schema::table('subscriptions', function (Blueprint $table) { $table->dropExpirable('ends_at'); }); }
使用方法
检索模型
检索有效模型
像往常一样处理。默认情况下,当到期日期到达时,模型将自动从结果中排除。
例如
// Get only valid and current subscriptions and exclude expired ones $subscriptions = Subscription::all();
以下所有示例以及后续示例,都与关系一起工作
$user = App\User::find(1); $subscriptions = $user->subscriptions();
检索所有模型
要禁用默认过滤并检索所有模型,忽略它们的到期日期
// Get all subscriptions $subscriptions = Subscription::withExpired()->get();
仅检索过期模型
使用onlyExpired作用域
// Get expired subscriptions $subscriptions = Subscription::onlyExpired()->get();
仅检索永不过期的模型
要获取不到期(到期日期属性为null
)的模型,请使用onlyEternal作用域
// Get unlimited subscriptions $subscriptions = Subscription::onlyEternal()->get();
检索自某日期起过期的模型
此包提供查询作用域以检索至少已过期给定时间的模型。使用expiredSince
作用域,并给它一个表示所需时间段的参数。
参数必须是字符串,其语法与Carbon sub
方法接受的语法相同(请参阅此处文档:[https://carbon.nesbot.com/docs/#api-addsub](https://carbon.nesbot.com/docs/#api-addsub))。
例如,假设您要从数据库中永久删除至少已过期一年的模型,查询将是
// Delete expired models since one year or more Subscription::expiredSince('1 year')->delete();
获取过期日期
要获取到期日期而无需知道其属性名称,请使用getExpirationDate方法
$subscription->getExpirationDate(); // Returns a date object
手动设置过期日期
基本方法
如果您知道到期日期属性的名称,您可以直接用日期对象(或null
用于永恒)填充此属性
// Create a new subscription valid for one month $subscription = new Subscription(); $subscription->ends_at = Carbon::now()->addMonth(); $subscription->save();
当然,它也适用于批量赋值,但请记住将您打算批量赋值的属性(此处为ends_at
)添加到模型的$fillable
属性中
// Create a new subscription valid for one month $subscription = Subscription::create([ 'plan' => 'premium', 'ends_at' => Carbon::now()->addMonth(), ]);
使用 expiresAt()
使用expiresAt
方法,将日期对象作为参数(或null
用于永恒)来手动设置到期日期。在Eloquent查询中,更改将直接保存到数据库中。对于单个模型,您仍然需要使用save
方法
// Create a new subscription valid for one month $subscription = new Subscription(); $subscription->expiresAt(Carbon::now()->addMonth()); $subscription->save();
// Set multiple subscriptions valid for one year Subscription::whereKey([1, 2, 3])->expiresAt(Carbon::now()->addYear());
使用 lifetime()
lifetime
方法提供了以字符串形式设置有效期期的更易读方式。参数必须是字符串,其语法与Carbon add
方法接受的语法相同(请参阅此处文档:[https://carbon.nesbot.com/docs/#api-addsub](https://carbon.nesbot.com/docs/#api-addsub))。
// Create a new subscription valid for one month $subscription = new Subscription(); $subscription->lifetime('1 month'); $subscription->save();
使现有模型过期
如果您想要一个模型过期,请在模型实例上使用expire
方法。这将设置到期日期为当前时间戳。
// Make a model expire $subscription->expire();
通过键过期模型
如果您知道模型的主键,您可以通过调用expireByKey
方法使其过期而无需检索它。除了接受单个主键作为其参数之外,expireByKey
方法还将接受多个主键、主键数组或主键集合
Subscription::expireByKey(1); Subscription::expireByKey(1, 2, 3); Subscription::expireByKey([1, 2, 3]); Subscription::expireByKey(collect([1, 2, 3]));
通过查询过期模型
您也可以对一组模型执行过期语句
Subscription::where('plan', 'basic')->expire();
恢复过期模型
模型过期后,您可以使用revive
方法将其重新激活。它接受一个可选参数,可以是日期对象或null
用于新有效期。如果没有参数,则重置为默认到期日期或如果没有设置默认到期日期,则将到期属性设置为null
(使模型永恒)。
// Reset validity with the default expiration date or set validity for unlimited period $subscription->revive(); // Set the model to expire in one month $subscription->revive(Carbon::now()->addMonth());
当然,它与查询一起工作
// Revive by query Subscription::where('plan', 'plus')->revive();
使现有模型永不过期
如果您想要一个模型永远不过期,只需将到期属性设置为null
即可。您可以手动执行此操作,或者对于现有模型,您可以使用提供的快捷方法makeEternal()
// Make a model eternal $subscription->makeEternal();
// Make eternal by query Subscription::where('plan', 'business')->makeEternal();
扩展模型的有效期
使用extendLifetimeBy
,您可以通过人类可读的周期(使用与lifetime
方法相同的语法)来延长模型的寿命
$subscription->extendLifetimeBy('1 month')->save();
同样,您还有缩短模型寿命的能力,使用shortenLifetimeBy
方法
缩短模型的有效期
$subscription->shortenLifetimeBy('3 days')->save();
将过期日期重置为默认值
您可以将过期日期重置为其默认值(null
或由 defaultExpiresAt
静态函数返回的日期)
$subscription->resetExpiration()->save();
获取模型的状态
您可以在可过期模型的实例上调用 isExpired()
和 isEternal()
方法。例如
if ($subscription->isExpired()) { $user->notify(new RenewalProposal($subscription)); }
清除过期记录
此软件包附带一个命令,用于从数据库中删除过期的记录
php artisan expirable:purge
您有两种方式来指示应该清除哪些模型
- 将它们的类添加到配置文件的
purge
数组中
'purge' => [ \App\Models\Subscription::class, ],
- 将一个或多个类作为清除命令的参数传递
php artisan expirable:purge "App\Models\Subscription" "App\Models\Coupon"
作为参数传递的模型具有优先权(配置文件中的 purge
数组将被忽略)。
您还可以指定一个时间段,以删除自给定时间段以来过期的模型,使用 since
选项(此选项的值传递给 expiredSince 查询范围)
php artisan expirable:purge "App\Models\Subscription" --since="2 months"
默认情况下,此命令将使用强制删除来清除模型。如果需要,您可以通过指定值为 soft
的 mode
选项来执行软删除
php artisan expirable:purge --mode=soft
⚠️ 注意,如果您尝试使用默认的 hard
模式清除依赖于具有外键约束的表的模型,您将必须指定约束的 "on delete" 属性的所需操作(例如,在迁移中使用 onDelete('cascade')、cascadeOnDelete() 或 nullOnDelete() 修饰符在外键上:https://laravel.net.cn/docs/10.x/migrations#foreign-key-constraints)或首先清除子模型(通过命令参数或配置文件中的数组排序以从子模型开始),以避免 SQL 错误。
许可证
开源软件,采用 MIT 许可证。