Since Laravel 8.5 there was a trait added to the framework that will allow you to prune models based on a date. This
trait is called Illuminate\Database\Eloquent\Prunable
and it will allow you to prune models based on a date.
This trait is useful when you have models that you want to delete based on a date. For example, you might have a model that stores logs and you want to delete logs that are older than a certain date.
In this article, we're going to look at how you can create a trait that will allow you to prune models based on a date.
What Are Prunable Models?
Prunable models are Eloquent models that can automatically delete old records based on specific criteria. This is particularly useful for:
- Log entries that accumulate over time
- Temporary data like password reset tokens
- Analytics data older than a retention period
- User sessions that have expired
- Notification records that are no longer needed
Using the Prunable Trait
To use the Prunable
trait you need to add it to your model and define a prunable
method that will return a query
builder instance. This query builder instance will be used to prune the models based on a date.
Here's an example of how you can use the Prunable
trait in a model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
class Log extends Model
{
use Prunable;
public function prunable()
{
return $this->where('created_at', '<', now()->subDays(30));
}
}
In this example, we have a Log
model that uses the Prunable
trait. We have defined a prunable
method that returns
a query builder instance that will delete logs that are older than 30 days.
Advanced Pruning Examples
Pruning Based on Multiple Conditions
You can combine multiple conditions in your pruning logic:
public function prunable()
{
return $this->where('created_at', '<', now()->subDays(30))
->where('status', 'processed')
->whereNull('important_flag');
}
Pruning with Relationships
You can also prune models based on related data:
public function prunable()
{
return $this->whereHas('user', function ($query) {
$query->where('deleted_at', '<', now()->subDays(90));
});
}
Schedule Pruning
To prune the models you need to schedule the pruning to run at a certain time. You can do this by adding a command
to your routes/console.php
file that will call the prune
method on the model.
Here's an example of how you can schedule the pruning of the Log
model:
<?php
use Illuminate\Support\Facades\Schedule;
Schedule::command('model:prune')->daily();
In this example, we're scheduling the model:prune
command to run daily. This command will call the prune
method
on the Log
model and delete logs that are older than 30 days.
Performance Considerations
When implementing prunable models, consider these performance aspects:
- Batch size: Large deletions can impact database performance
- Indexing: Ensure columns used in pruning conditions are indexed
- Timing: Run pruning during low-traffic periods
- Monitoring: Track deletion counts and query performance
For comprehensive database performance monitoring, see our guide on Laravel Database Performance Guide which covers query optimization, caching, and debugging techniques.
Best Practices
1. Test Your Pruning Logic
Always test your pruning conditions in a development environment first:
// Test what would be pruned without actually deleting
$countToPrune = Log::prunable()->count();
Log::info("Would prune {$countToPrune} records");
2. Add Safety Checks
Include safety mechanisms to prevent accidental mass deletions:
public function prunable()
{
$cutoffDate = now()->subDays(30);
// Safety check: don't delete if cutoff is too recent
if ($cutoffDate->gt(now()->subDays(7))) {
return $this->whereRaw('1 = 0'); // Return empty query
}
return $this->where('created_at', '<', $cutoffDate);
}
3. Log Pruning Activity
Monitor your pruning operations by adding logging:
protected static function booted()
{
static::pruned(function ($model) {
Log::info('Pruned model', ['id' => $model->id, 'model' => get_class($model)]);
});
}
Related Laravel Features
Prunable models work well with other Laravel database features:
- Laravel Database Performance Guide for comprehensive optimization
- Laravel optimize command for application performance
- Virtual database columns for computed fields
- Custom collections for handling pruned data
- MySQL ordering techniques for efficient queries
Conclusion
Prunable Eloquent models provide an elegant solution for automatically cleaning up old data in your Laravel applications. By implementing the Prunable
trait and scheduling regular pruning operations, you can maintain database performance and comply with data retention policies without manual intervention.
Remember to always test your pruning logic thoroughly and monitor the performance impact of deletion operations on your database.