Skip to content

Model Traits

Traits you can add to your Eloquent models for extra functionality.

HasDateScopes

Adds 14 query scopes for common date ranges. All accept an optional $column parameter (default: created_at).

php
use Anil\FastApiCrud\Concerns\HasDateScopes;

class Post extends Model
{
    use HasDateScopes;
}

Available Scopes

ScopeDescription
today($column)Records from today
yesterday($column)Records from yesterday
thisWeek($column)Monday to now
lastWeek($column)Last Monday to Sunday
monthToDate($column)1st of month to now
thisMonth($column)Entire current month
lastMonth($column)Entire previous month
quarterToDate($column)Start of quarter to now
lastQuarter($column)Previous quarter
yearToDate($column)January 1 to now
lastYear($column)Last 12 months
last7Days($column)Last 7 days
last30Days($column)Last 30 days
date($search, $column)Custom range: "YYYY-MM-DD to YYYY-MM-DD"

Usage

php
// Default column (created_at)
Post::query()->today()->get();
Post::query()->lastWeek()->get();
Post::query()->last30Days()->get();

// Custom column
Post::query()->today('published_at')->get();
Post::query()->lastMonth('updated_at')->get();

// Custom range
Post::query()->date('2025-01-01 to 2025-01-31')->get();
Post::query()->date('2025-03-15 to 2025-03-15')->get();  // Single day
Post::query()->date('2025-01-01')->get();  // Same day start and end

// Chain with other scopes
Post::query()
    ->thisMonth()
    ->where('active', true)
    ->get();

The date() scope silently returns the query unmodified if the input is null, empty, or unparseable.

All scopes qualify the column with the table name ({table}.{column}) to avoid ambiguity in joins.

Use with Filters

These scopes work with the ?filters= query parameter:

GET /posts?filters={"today":1}
GET /posts?filters={"lastWeek":1}
GET /posts?filters={"date":"2025-01-01 to 2025-01-31"}

UUID primary keys

This package does not ship a UUID trait. Use Laravel's first-party traits — they set incrementing/keyType, fill the key on creating, and add UUID-aware route model binding:

php
use Illuminate\Database\Eloquent\Concerns\HasUuids;          // UUID v7 (time-ordered, recommended)
// use Illuminate\Database\Eloquent\Concerns\HasVersion4Uuids; // ordered UUID

class Post extends Model
{
    use HasUuids;
}

Ordered UUIDs (v7) are recommended for primary keys because of their B-tree index locality. Use a pure-random v4 only when you must hide record creation order.

Migration

php
Schema::create('posts', function (Blueprint $table) {
    $table->uuid('id')->primary();  // Use uuid instead of id()
    $table->string('name');
    $table->timestamps();
});

Usage

php
$post = Post::create(['name' => 'Test']);
$post->id; // "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"

AnonymizesOnDelete

Anonymizes unique column values on soft delete to prevent constraint violations.

php
use Anil\FastApiCrud\Concerns\AnonymizesOnDelete;

class User extends Model
{
    use SoftDeletes, AnonymizesOnDelete;
}

What It Does

When a model is soft-deleted, all unique (non-primary) columns get _{timestamp} appended:

Before delete: email = "john@example.com"
After delete:  email = "john@example.com_1705312800"

This prevents unique constraint violations when creating a new record with the same value while the old one is soft-deleted.

Requirements

  • Model must use the SoftDeletes trait
  • Controlled by fast-api.soft_delete.anonymize_unique_columns config (default: true)
  • Only affects columns that are part of a unique index (not primary key)
  • Uses saveQuietly() to avoid triggering additional model events

ReplicatesWithRelations

Replicate a model along with all its loaded relations.

php
use Anil\FastApiCrud\Concerns\ReplicatesWithRelations;

class Post extends Model
{
    use ReplicatesWithRelations;
}

Usage

php
// Load the model with relations you want to replicate
$post = Post::with(['tags', 'comments', 'author'])->find(1);

// Replicate everything
$clone = $post->replicateWithRelations();
// Returns a saved copy of the post with all relations duplicated

Supported Relations

Relation TypeBehavior
BelongsToReplicates the related model recursively
MorphToReplicates the related model recursively
HasOneReplicates the related model and saves to new parent
MorphOneReplicates the related model and saves to new parent
HasManyReplicates each related model and saves to new parent
MorphManyReplicates each related model and saves to new parent
BelongsToManySyncs the same IDs to the new model (no duplication)
MorphToManySyncs the same IDs to the new model (no duplication)

Not Supported

HasOneThrough and HasManyThrough relations throw an Exception with a descriptive message.

Castable Attributes

The trait automatically re-applies castable attributes (numeric, boolean, string, json) to the replicated model via matchingCastableAttributes() to ensure proper type handling during replication.

Recursive Replication

If a related model also uses ReplicatesWithRelations, it will be replicated recursively with its own relations. Otherwise, a simple replicate() is used.

Released under the MIT License.