aa-engineering / laravel-scheduled-reminders
A Laravel package for scheduling and managing reminders with morphable relationships
Installs: 6
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/aa-engineering/laravel-scheduled-reminders
Requires
- php: ^8.2|^8.3|^8.4
- illuminate/contracts: ^11.0|^12.0
- illuminate/database: ^11.0|^12.0
- illuminate/notifications: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^9.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
README
A Laravel package for scheduling and managing reminders with morphable relationships. Schedule notifications to be sent at specific times, attach them to any model, and track their delivery status.
Features
- ๐ Schedule reminders for any date/time
- ๐ Polymorphic relationships - attach reminders to any model
- ๐ Track delivery status - know when reminders were sent
- ๐ฏ Source tracking - link reminders to their originating models (tasks, events, etc.)
- ๐งน Automatic pruning - clean up old sent reminders
- ๐จ Flexible data storage - store custom data with each reminder
- โก Queue support - send reminders via queue workers
- ๐งช Fully tested - comprehensive test suite included
Installation
You can install the package via composer:
composer require aa-engineering/laravel-scheduled-reminders
Publish and run the migrations:
php artisan vendor:publish --tag="scheduled-reminders-migrations"
php artisan migrate
Optionally, publish the config file:
php artisan vendor:publish --tag="scheduled-reminders-config"
This is the contents of the published config file:
return [ 'prune_after_days' => env('REMINDERS_PRUNE_AFTER_DAYS', 30), 'log_errors' => env('REMINDERS_LOG_ERRORS', true), 'queue_connection' => env('REMINDERS_QUEUE_CONNECTION', null), 'queue_name' => env('REMINDERS_QUEUE_NAME', 'default'), ];
Usage
1. Add the trait to your models
Add the Remindable
trait to any model that should receive reminders:
use AAEngineering\ScheduledReminders\Traits\Remindable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Remindable; // ... }
2. Create a reminder
use App\Notifications\TaskDueNotification; $user = User::find(1); $task = Task::find(1); // Schedule a reminder for tomorrow $user->remindAt( notification: TaskDueNotification::class, source: $task, sendAt: now()->addDay(), data: ['custom' => 'data'] );
3. Query reminders
// Get all reminders $allReminders = $user->reminders; // Get pending reminders (due but not sent) $pendingReminders = $user->pendingReminders; // Get future reminders (scheduled for later) $futureReminders = $user->futureReminders; // Get sent reminders $sentReminders = $user->sentReminders; // Check if user has pending reminders if ($user->hasPendingReminders()) { // ... }
4. Remove reminders
// Remove reminders for a specific source $user->removeReminder($task); // Remove all pending reminders $user->removePendingReminders();
5. Send reminders
Set up a scheduled task in your routes/console.php
:
use Illuminate\Support\Facades\Schedule; Schedule::command('reminders:send')->everyFiveMinutes();
Or manually send reminders:
# Send all pending reminders php artisan reminders:send # Limit the number of reminders to send php artisan reminders:send --limit=100 # Dry run (see what would be sent without actually sending) php artisan reminders:send --dry-run
6. Automatic pruning
Enable automatic pruning of sent reminders by adding to your routes/console.php
:
use Illuminate\Support\Facades\Schedule; Schedule::command('model:prune')->daily();
Sent reminders older than the configured prune_after_days
will be automatically deleted.
Advanced Usage
Custom Notification Data
You can store any custom data with your reminders:
$user->remindAt( notification: CustomNotification::class, source: $task, sendAt: now()->addHours(2), data: [ 'priority' => 'high', 'category' => 'urgent', 'custom_field' => 'value', ] );
Access the data in your notification:
class CustomNotification extends Notification { public function __construct( public Model $source, public array $data ) {} public function toMail($notifiable) { $priority = $this->data['priority'] ?? 'normal'; return (new MailMessage) ->subject("Task Reminder - Priority: {$priority}") ->line($this->data['custom_field']); } }
Notification Constructor Patterns
The package supports flexible notification constructors. Here are all possible patterns:
1. Constructor with Source Only
class SimpleNotification extends Notification { public function __construct( public Model $source ) {} } // Usage $user->remindAt( notification: SimpleNotification::class, source: $task, sendAt: now()->addDay() );
2. Constructor with Source and Data
class DataNotification extends Notification { public function __construct( public Model $source, public array $data ) {} } // Usage $user->remindAt( notification: DataNotification::class, source: $task, sendAt: now()->addDay(), data: ['priority' => 'high'] );
3. Constructor with Data Only
class DataOnlyNotification extends Notification { public function __construct( public array $data ) {} } // Usage $user->remindAt( notification: DataOnlyNotification::class, sendAt: now()->addDay(), data: ['message' => 'Custom reminder'] );
4. No Constructor Parameters
class StaticNotification extends Notification { // No constructor needed public function toMail($notifiable) { return (new MailMessage) ->line('Static reminder message'); } } // Usage $user->remindAt( notification: StaticNotification::class, sendAt: now()->addDay() );
5. Constructor with Custom Parameters
class CustomNotification extends Notification { public function __construct( public string $title, public int $priority = 1 ) {} } // Usage - Custom parameters are passed via data array $user->remindAt( notification: CustomNotification::class, sendAt: now()->addDay(), data: [ 'title' => 'Important Task', 'priority' => 5 ] );
Direct Model Access
You can also work with the Reminder
model directly:
use AAEngineering\ScheduledReminders\Models\Reminder; // Find all pending reminders across the system $pending = Reminder::whereNull('sent_at') ->where('send_at', '<=', now()) ->get(); // Find reminders for a specific source $taskReminders = Reminder::where('source_type', Task::class) ->where('source_id', $taskId) ->get();
Using with Queues
Your notification classes can implement ShouldQueue
as usual:
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Notification; class TaskDueNotification extends Notification implements ShouldQueue { // This notification will be queued when sent }
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.