Skip to content

Scheduling

The Schedule attribute provides an elegant way to create and manage WordPress cron jobs. It allows you to easily schedule recurring tasks in your WordPress application using multiple approaches: predefined schedules, enum values, or custom intervals.

To schedule a recurring task, simply add the Schedule attribute to your method:

use Pollora\Attributes\Schedule;
class Maintenance
{
#[Schedule('daily')]
public function cleanupDatabase(): void
{
// This method will run once per day
// The hook name will be: maintenance_cleanup_database
}
}

The framework provides an Every enum for type-safe scheduling with predefined intervals:

use Pollora\Attributes\Schedule;
use Pollora\Schedule\Every;
class Maintenance
{
#[Schedule(Every::HOUR)]
public function pingSlack(): void
{
// Runs every hour
}
#[Schedule(Every::DAY)]
public function dailyBackup(): void
{
// Runs once per day
}
#[Schedule(Every::WEEK)]
public function weeklyReport(): void
{
// Runs once per week
}
#[Schedule(Every::MONTH)]
public function monthlyCleanup(): void
{
// Runs once per month (custom schedule automatically registered)
}
#[Schedule(Every::YEAR)]
public function yearlyArchive(): void
{
// Runs once per year (custom schedule automatically registered)
}
}
  • Every::HOUR - Runs once every hour (uses WordPress hourly)
  • Every::TWICE_DAILY - Runs twice per day (uses WordPress twicedaily)
  • Every::DAY - Runs once per day (uses WordPress daily)
  • Every::WEEK - Runs once per week (uses WordPress weekly)
  • Every::MONTH - Runs once per month (automatically creates custom schedule)
  • Every::YEAR - Runs once per year (automatically creates custom schedule)

WordPress provides several default scheduling intervals that you can still use with strings:

  • hourly - Runs once every hour
  • twicedaily - Runs twice per day
  • daily - Runs once per day
  • weekly - Runs once per week

For precise timing control, use the Interval class which provides a fluent API:

use Pollora\Attributes\Schedule;
use Pollora\Schedule\Interval;
class Maintenance
{
#[Schedule(new Interval(hours: 3, minutes: 30))]
public function checkFeeds(): void
{
// Runs every 3 hours and 30 minutes
}
#[Schedule(new Interval(
days: 1,
hours: 12,
minutes: 15,
display: 'Daily plus 12h15m'
))]
public function complexTask(): void
{
// Runs every 1 day, 12 hours, and 15 minutes
}
#[Schedule(new Interval(weeks: 2, display: 'Bi-weekly'))]
public function biweeklyTask(): void
{
// Runs every 2 weeks
}
}
  • seconds: int = 0 - Additional seconds
  • minutes: int = 0 - Additional minutes
  • hours: int = 0 - Additional hours
  • days: int = 0 - Additional days
  • weeks: int = 0 - Additional weeks
  • display: string = 'Custom schedule' - Human-readable description

For backward compatibility, you can still create custom schedules using arrays:

class Maintenance
{
#[Schedule(
['interval' => 3600 * 6, 'display' => '6 hours']
)]
public function performCheck(): void
{
// Runs every 6 hours
}
}

The custom schedule array requires:

  • interval: Time in seconds between executions
  • display: Human-readable name for the schedule

By default, the hook name is generated from the class and method names, but you can specify a custom hook name:

use Pollora\Schedule\Every;
use Pollora\Schedule\Interval;
class Maintenance
{
// With string schedule
#[Schedule('hourly', hook: 'custom_maintenance_hook')]
public function performTask(): void
{
// Uses 'custom_maintenance_hook' instead of 'maintenance_perform_task'
}
// With Every enum
#[Schedule(Every::DAY, hook: 'daily_cleanup')]
public function cleanup(): void
{
// Uses 'daily_cleanup' hook name
}
// With Interval class
#[Schedule(new Interval(hours: 6), hook: 'six_hourly_check')]
public function checkSystem(): void
{
// Uses 'six_hourly_check' hook name
}
}

You can pass additional arguments to your scheduled function with any schedule type:

use Pollora\Schedule\Every;
use Pollora\Schedule\Interval;
class Maintenance
{
// With string schedule
#[Schedule(
'daily',
hook: 'cleanup_task',
args: ['type' => 'full', 'force' => true]
)]
public function cleanup(array $args): void
{
$type = $args['type']; // 'full'
$force = $args['force']; // true
// Perform cleanup based on arguments
}
// With Every enum and arguments
#[Schedule(Every::DAY, hook: 'custom_hook', args: ['type' => 'full'])]
public function updateIndex(array $args): void
{
// Process with arguments
}
// With Interval class and arguments
#[Schedule(
new Interval(hours: 2, minutes: 30),
hook: 'data_sync',
args: ['source' => 'api', 'batch_size' => 100]
)]
public function syncData(array $args): void
{
// Sync data with specified parameters
}
}

Here’s a comprehensive example showing various ways to use the Schedule attribute:

use Pollora\Attributes\Schedule;
use Pollora\Schedule\Every;
use Pollora\Schedule\Interval;
class SystemMaintenance
{
// Using Every enum (recommended)
#[Schedule(Every::DAY)]
public function dailyCleanup(): void
{
// Daily cleanup using enum
}
// Custom interval using Interval class
#[Schedule(new Interval(hours: 4, display: '4 hours'))]
public function systemHealthCheck(): void
{
// Runs every 4 hours
}
// Monthly schedule with custom hook (auto-registered)
#[Schedule(Every::MONTH, hook: 'monthly_reports')]
public function generateReports(): void
{
// Monthly report generation
}
// Complex interval with arguments
#[Schedule(
new Interval(hours: 2, minutes: 30),
hook: 'data_sync',
args: ['type' => 'incremental', 'source' => 'api']
)]
public function syncData(array $args): void
{
// Runs every 2.5 hours with arguments
}
// Legacy string syntax (still supported)
#[Schedule('twicedaily')]
public function legacyTask(): void
{
// Backward compatibility
}
// Legacy array syntax (still supported)
#[Schedule(
['interval' => 3600 * 6, 'display' => '6 hours'],
hook: 'legacy_check'
)]
public function legacyCustomTask(): void
{
// Backward compatibility with arrays
}
}
TypeSyntaxUse CaseCustom Registration
Every EnumEvery::DAYType-safe, predefined intervalsAuto for MONTH/YEAR
Interval Classnew Interval(hours: 2)Precise custom timingAlways
String'daily'WordPress built-insNever
Array['interval' => 3600]Legacy custom intervalsAlways
  1. Hook names are automatically generated in snake_case format if not specified:

    • For a class DatabaseMaintenance with method cleanupOldRecords
    • The generated hook name would be database_maintenance_cleanup_old_records
  2. The Schedule attribute ensures that events are only registered once through automatic discovery.

  3. Custom schedules are automatically registered when using:

    • Every::MONTH and Every::YEAR enum values
    • Interval class instances
    • Legacy array syntax with custom intervals
  4. All syntax variations support the same parameters:

    • hook: string - Custom hook name
    • args: array - Arguments passed to the scheduled method