alajusticia/laravel-expirable

使 Eloquent 模型具有过期功能

资助包维护!
Ko Fi

v2.3 2024-02-28 11:44 UTC

This package is auto-updated.

Last update: 2024-08-31 21:31:24 UTC


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"

默认情况下,此命令将使用强制删除来清除模型。如果需要,您可以通过指定值为 softmode 选项来执行软删除

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 许可证