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

v1.0.4 2025-10-11 19:06 UTC

This package is auto-updated.

Last update: 2025-10-11 19:07:57 UTC


README

Latest Version on Packagist Total Downloads

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.