mvdnbrk/laravel-model-expires
Installation:
composer require mvdnbrk/laravel-model-expires
Publish the config (if needed) with:
php artisan vendor:publish --provider="Mvdnbrk\EloquentExpirable\EloquentExpirableServiceProvider"
Add the trait to your Eloquent model:
use Mvdnbrk\EloquentExpirable\Expirable;
class Subscription extends Model
{
use Expirable;
}
Add the expires_at column to your migration:
Schema::create('subscriptions', function (Blueprint $table) {
$table->expires(); // Adds `expires_at` column with nullable timestamp
});
Run migrations and start using:
$subscription = Subscription::create(['expires_at' => now()->addDays(30)]);
Check if a model is expired:
if ($subscription->isExpired()) {
// Handle expiration logic
}
Force-expire a model:
$subscription->expire();
Setting Expiration Dates:
expiresAt() to set expiration dynamically:
$subscription->expiresAt(now()->addMonth());
$subscription->save();
expire() to set expiration to now:
$subscription->expire();
Querying Expired Models:
$expired = Subscription::expired()->get();
$active = Subscription::notExpired()->get();
Soft Deletion Integration:
SoftDeletes for auto-purging:
use Illuminate\Database\Eloquent\SoftDeletes;
class Subscription extends Model
{
use Expirable, SoftDeletes;
protected $dates = ['expires_at', 'deleted_at'];
}
Subscription::observe(SubscriptionExpiredObserver::class);
Custom Expiration Logic:
isExpired() for business rules:
public function isExpired(): bool
{
return parent::isExpired() || $this->trial_ended_at < now();
}
expires_at field in API responses for client-side expiration tracking.Subscription::where('expires_at', '<', now())->delete();
expires_at:
$rules = ['expires_at' => 'required|date|after:today'];
Column Name Conflicts:
expires_at conflicts with existing columns, override the column name:
class Subscription extends Model
{
use Expirable;
const EXPIRES_AT = 'subscription_expires_at';
}
config/eloquent-expirable.php:
'column' => 'custom_expires_at',
Timezone Issues:
expires_at uses the correct timezone. Set the model's $dateFormat or use Carbon’s setTimezone():
$subscription->expiresAt(now()->timezone('UTC')->addDays(30));
Soft Deletes + Expirable:
SoftDeletes, ensure $dates includes both expires_at and deleted_at to avoid serialization issues.Database Indexes:
expires_at for faster queries:
Schema::table('subscriptions', function (Blueprint $table) {
$table->index('expires_at');
});
expires_at value to debug timezone/date issues:
\Log::debug('Expires at:', [$this->expires_at, $this->expires_at->toDateTimeString()]);
expires_at column in the database and the isExpired() method in the model.Custom Scopes:
expiredBetween):
public function scopeExpiredBetween($query, $from, $to)
{
return $query->whereBetween('expires_at', [$from, $to]);
}
Event Triggers:
ModelExpired):
use Mvdnbrk\EloquentExpirable\Events\ModelExpired;
ModelExpired::listen(function ($model) {
// Send notification, log, etc.
});
Custom Expiration Rules:
shouldExpire() for dynamic expiration logic:
public function shouldExpire(): bool
{
return $this->trial_active && parent::shouldExpire();
}
Batch Processing:
Subscription::chunk(100, function ($subscriptions) {
foreach ($subscriptions as $subscription) {
if ($subscription->isExpired()) {
$subscription->delete(); // or softDelete()
}
}
});
How can I help you explore Laravel packages today?