Get "PHP 8 in a Nuthshell" (Now with PHP 8.4)
Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

Automatically remove models using Prunable trait in Laravel 8.x

I recently saw a tweet by Philo Hermans which states the slick use of a recently added Prunable trait in Laravel 8.x

Essentially, from the version 8.50.0, Laravel comes with a Prunable trait, which is when added to the models, allows to remove obsolete model records.

Using Prunable trait

For this, all you need is to add the Illuminate\Database\Eloquent\Prunable trait to the model that you want to make prunable. Next, you’ll need to implement the prunable method where you need to write the condition that determines which records to prune.

For instance, if you want to prune all the model records older than 15 days, this is how you can do so.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;

    use Prunable; 

    /**
     * Determines the prunable query.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function prunable()
    {
        return $this->where('created_at', '<=', now()->subDays(15));
    }
}

Once that is done, you’ll then need to schedule the db:prune artisan command in your App\Console\Kernel class like so.

/**
 * Define the application's command schedule.
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->command('db:prune')->daily();
}

This will allow Laravel to scan and detect all the models that have the Prunable trait under the app/models folder and prune the model records accordingly.

The pruning method

Now, there might be a scenario where the model records might have some additional resources associated with them. Obviously, when the model records are being pruned, you also want these associated resources to be removed as well.

For this exact purpose, the pruning method can be used alongside the prunable method. This method will be called before the model is deleted.

So, for instance, if you want the associated S3 files to be deleted with the model records, this is how you can do so.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;

class File extends Model
{
    use SoftDeletes;

    use Prunable; 

    /**
     * Determines the prunable query.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function prunable()
    {
        return $this->where('created_at', '<=', now()->subDays(15));
    }

    /**
     * Prepare the model for pruning.
     *
     * @return void
     */
    protected function pruning()
    {
        // Remove the associated file from S3 before deleting the model
        Storage::disk('s3')->delete($this->filename)
    }
}
Learn the fundamentals of PHP 8 (including 8.1, 8.2, and 8.3), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

Like this article?

Buy me a coffee

👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.

Comments?