Limit the number of model records by amount or date.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laragear\Capstone\HasCap;
use Laragear\Capstone\Keep;
class Draft extends Model
{
use HasCap;
/**
* Limits the model records in the table.
*/
public function keep(Keep $keep)
{
$keep->same('post_id')->by(10);
}
}
Your support allows me to keep this package free, up-to-date and maintainable.
- PHP 8.2
- Laravel 11 or later
You can install the package via Composer.
composer require laragear/capstone
This library can limit how many models can be persisted in a table. The only requisite is a primary key, and that these models share a particular column value.
For example, imagine a Post
model having Drafts
. To limit the amount of drafts present in the database for that post, this library does it automatically using the Laragear\Capstone\HasCap
trait. By default, it uses a limit of 5. It only requires a column to group the drafts to keep, which would be post_id
.
Find the Eloquent Model you want to limit, add the Laragear\Capstone\HasCap
trait with the keep()
method.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laragear\Capstone\HasCap;
use Laragear\Capstone\Keep;
class Draft extends Model
{
use HasCap;
public function keep(Keep $keep)
{
//
}
}
The next step is to configure which column to group the models to keep, otherwise the whole table would be affected. The keep()
method receives a Laragear\Capstone\Keep
instance you can use to point out the column (or columns) to group the models.
For example, we can use the post_id
to group the drafts for a particular post with the same()
method and the name of the column, which will exclude drafts with different post_id
from the operation.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id');
}
You may also set more than one column to match more records in the database.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id', 'user_id');
}
Alternatively, you may use a callback that modifies the query to group the records to limit. The callback receives the Illuminate\Database\Eloquent\Builder
instance you can adjust to your liking.
use Laragear\Capstone\Keep;
use Illuminate\Contracts\Database\Eloquent\Builder
public function keep(Keep $keep)
{
$keep->same(function (Builder $query) {
$query
->where('post_id', $this->post_id)
->whereRelation('post.user', 'is_vip', false)
});
}
Important
The query is using only to group the records that will be kept or deleted, not to apply limits.
By default, the records are limited by 5. Each time a new record is inserted into the database, the oldest (by their primary key) is deleted. You may change the amount using the by()
method.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id')->by(10);
}
You also disable the limit by setting it to 0
(zero) or using all()
. In that case, you should complement this with a time limit.
$keep->same('post_id')->all()->after('-14 days');
Tip
You can combine both by()
and after()
to limit records by amount and time, respectively.
You can also limit the records to keep by a relative date in the past using the after()
method, which accepts a DateTimeInterface
like a Carbon
instance or a string to be parsed through strtotime
.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id')->after('-14 days');
}
By default, it uses the model creation timestamp to pick which records should be kept. You may use a different column by setting its name a second parameter.
$keep->same('post_id')->after(now()->subMonth(), 'updated_at');
Tip
You can combine both by()
and after()
to limit records by amount and time, respectively.
When the models to keep are queried to exclude them from the deletion, these are ordered by their primary key in descending order. If your models have unordered primary keys, like UUID v4, or strings, you may change the query order by their creation timestamp using latest()
and oldest()
.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id')->oldest();
}
Both methods also accept the column to sort the records if these don't have a creation timestamp, or you need to sort them using another column.
$cap->same('post_id')->latest('saved_at');
$cap->same('post_id')->oldest('published_at');
Records that are not kept will be removed using the delete()
query method. If your model uses soft deletes, you may remove it completely from the databases using forceDelete()
method.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id')->forceDelete();
}
In case you require to issue a condition for force deletion, you can use a variable that evaluates to true or false, or a callback that receives the model and returns the result of the condition.
$keep->same('post_id')->forceDelete(fn ($draft) => $draft->author->isNotVip());
If you require to disable deleting out-of-bounds records, then you can use deleteWhen()
and deleteUnless()
with a condition or callback that evaluates to truthy or falsy, respectively, as long it's not null
.
use Laragear\Capstone\Keep;
public function keep(Keep $keep)
{
$keep->same('post_id')->deleteWhen($this->isVip());
}
- There are no singletons using a stale app instance.
- There are no singletons using a stale config instance.
- There are no singletons using a stale request instance.
- There are no static properties written during a request.
There should be no problems using this package with Laravel Octane.
If you discover any security related issues, issue a Security Advisor
This specific package version is licensed under the terms of the MIT License, at time of publishing.
Laravel is a Trademark of Taylor Otwell. Copyright © 2011-2025 Laravel LLC.