laracraft-tech/laravel-date-scopes
Add powerful, ready-made date query scopes to Laravel Eloquent models. Use the DateScopes trait to query records for today, last week, month-to-date, last year (with custom start dates), and more—fully chainable with builder methods and aggregations.
Installation:
composer require laracraft-tech/laravel-date-scopes
No additional configuration is required for basic usage.
First Use Case:
Apply the DateScopes trait to any Eloquent model:
use LaracraftTech\LaravelDateScopes\DateScopes;
class Transaction extends Model
{
use DateScopes;
}
Now query records using built-in scopes:
// Get today's transactions
Transaction::ofToday();
// Get last week's transactions
Transaction::ofLastWeek();
Where to Look First:
Basic Date Filtering:
// Filter by predefined periods
$today = Transaction::ofToday();
$lastWeek = Transaction::ofLastWeek();
// Custom periods
$last30Days = Transaction::ofLastDays(30);
Chaining with Aggregations:
// Sum amounts for today
$todayTotal = Transaction::ofToday()->sum('amount');
// Average for last month
$monthAvg = Transaction::ofLastMonth()->avg('amount');
Custom Columns:
// Use a non-standard column (e.g., 'approved_at')
$approvedToday = Transaction::ofToday(column: 'approved_at');
Custom Start Dates:
// Filter from a specific date
$year2020 = Transaction::ofLastYear(startFrom: '2020-01-01');
Inclusive/Exclusive Ranges:
// Override global default (e.g., include today)
$inclusiveLastWeek = Transaction::ofLastWeek(customRange: DateRange::INCLUSIVE);
Period-to-Date Queries:
// Get data from start of year to now
$yearToDate = Transaction::yearToDate();
API Controllers: Use scopes to filter resources dynamically:
public function index(Request $request)
{
$query = Transaction::query();
if ($request->has('period')) {
$query->{$request->period}(); // e.g., "ofLastWeek"
}
return $query->get();
}
Jobs/Commands: Schedule reports for specific periods:
// In a scheduled job
$dailyRevenue = Transaction::ofToday()->sum('amount');
Views: Pass scoped data to Blade templates:
$weeklySales = Transaction::ofLastWeek()->get();
return view('reports.weekly', compact('weeklySales'));
Testing: Mock dates for consistent test results:
use Carbon\Carbon;
beforeEach(function () {
Carbon::setTestNow(Carbon::now()->startOfDay());
});
Inclusive vs. Exclusive Ranges:
ofLastWeek excludes today).Transaction::ofLastWeek(customRange: DateRange::INCLUSIVE);
Centuries/Millenniums:
Custom Columns:
$table->timestamp('custom_column') in migrations.Time Zones:
Transaction::ofToday()->setTimeZone('America/New_York');
Performance:
ofLastDecade) on large tables without indexing.$table->timestamp('created_at')->index();
Chaining Conflicts:
// ❌ Avoid: May return empty results if today is excluded
Transaction::ofLastWeek()->ofToday();
orWhere or rebuild the query.Log Raw Queries: Enable query logging to verify scope behavior:
DB::enableQueryLog();
Transaction::ofLastWeek()->get();
dd(DB::getQueryLog());
Test Edge Cases:
ofLastYear on Jan 1).Carbon::setTestNow(Carbon::parse('2023-01-01'));
$result = Transaction::ofLastYear()->count(); // Should return 0
Custom Scope Validation:
startFrom dates:
if (!Carbon::parse($startFrom)->isValid()) {
throw new \InvalidArgumentException("Invalid date format");
}
Add Custom Scopes: Extend the trait or create a new one:
trait CustomDateScopes
{
public function scopeOfLastBusinessDays($query, $days)
{
// Custom logic to exclude weekends
}
}
Override Default Behavior: Publish and modify the config:
php artisan vendor:publish --tag="date-scopes-config"
Then update config/date-scopes.php:
'default_range' => DateRange::INCLUSIVE->value,
Localize Date Logic: Override date calculations for specific models:
class FiscalYearModel extends Model
{
use DateScopes;
public function scopeOfFiscalYear($query)
{
// Custom fiscal year logic
}
}
Use with Soft Deletes:
Scopes work with soft-deleted models, but ensure withTrashed() is used if needed:
Transaction::withTrashed()->ofLastWeek()->get();
Combine with API Resources:
public function toArray($request)
{
return [
'today' => Transaction::ofToday()->count(),
'last_week' => Transaction::ofLastWeek()->count(),
];
}
Laravel Nova: Use scopes in Nova toolbars for quick filtering:
Toolbar::make()
->append(
Link::make('Today', route('transactions.today'))
->asMethod('GET')
->canSee(fn () => auth()->check())
);
Dynamic Scopes: Create a dynamic scope resolver:
public function scopeOfPeriod($query, $period)
{
$method = "of{$period}";
return $method ? $query->$method() : $query;
}
Usage:
Transaction::ofPeriod('LastWeek');
How can I help you explore Laravel packages today?