Skip to content

v10: Breaking changes for PHP 8.4 and Laravel 12#1957

Merged
freekmurze merged 11 commits intomainfrom
v10
Feb 17, 2026
Merged

v10: Breaking changes for PHP 8.4 and Laravel 12#1957
freekmurze merged 11 commits intomainfrom
v10

Conversation

@freekmurze
Copy link
Member

@freekmurze freekmurze commented Feb 15, 2026

Summary

This is the v10 major release branch. It requires PHP 8.4+ and Laravel 12+, and contains several breaking changes aimed at modernizing the codebase and addressing long-standing community requests.

Serializable events

All events now carry primitive data (string $diskName, string $backupName) instead of BackupDestination or BackupDestinationStatus objects. This means events can be safely used with queued listeners, which was previously impossible (#1860).

Breaking: If you listen to backup events, update your listeners to use $event->diskName and $event->backupName instead of $event->backupDestination.

Decoupled notifications from events

Events now always fire, even when --disable-notifications is used. Notifications are gated separately via EventHandler::enable() / EventHandler::disable(). This fixes the issue where BackupWasSuccessful was never fired with --disable-notifications (#1744), and also means encryption (which depends on the BackupZipWasCreated event) works correctly regardless of notification settings.

Replaced ConsoleOutput singleton with BackupLogger

The global consoleOutput() helper has been replaced by backupLogger(), which uses a listener pattern. Console output is registered as a listener in the base command, making it easy to add custom log destinations.

Notification discovery replaced with explicit map

EventHandler now uses an explicit $eventToNotificationMap array instead of string manipulation to find notification classes. Falls back to config-based discovery for custom notification classes.

Resilient multi-destination backups

Added continue_on_failure config option for backup destinations. When enabled, a failure on one destination won't abort the entire backup — it fires a BackupHasFailed event for the failed destination and continues. Only throws if all destinations fail (#1708, #1934, #1939).

Health check failure details

BackupDestinationStatus now collects all health check failures instead of stopping at the first one. UnhealthyBackupWasFound event carries a failureMessages collection. backup:monitor and backup:list commands display all failure reasons (#1509).

New enums

  • Encryption enum (none, default, aes128, aes192, aes256) replaces the old mixed null/false/string/int encryption config
  • DumpFilenameBase enum (database, connection) replaces stringly-typed config values

EncryptBackupArchive uses Config DTO

The encryption listener now receives the Config DTO via constructor injection instead of calling config() directly.

DefaultStrategy uses Config DTO

The default cleanup strategy now uses the typed Config DTO ($this->config->cleanup->defaultStrategy->keepAllBackupsForDays, etc.) instead of raw array access. The recursive removeOldBackupsUntilUsingLessThanMaximumStorage method was also replaced with a while loop.

New command options

Graceful handling of missing directories

FileSelection now warns via backupLogger() instead of failing when an included directory doesn't exist (#1671).

Default excludes

storage/framework is now excluded by default (#1325).

Backup verification

New verify_backup config option. When enabled, the zip archive is opened after creation to verify it's valid and non-empty.

Generic webhook notification channel

New webhook notification channel that POSTs JSON to a configurable URL. Works with Mattermost, Microsoft Teams, or any custom integration (#1711). All notification classes now include a toWebhook() method.

Breaking changes

  • PHP 8.4+ required
  • Laravel 12+ required
  • All events changed from carrying domain objects to carrying primitive data
  • consoleOutput() helper replaced by backupLogger()
  • ConsoleOutput class removed
  • BackupJob::disableNotifications() removed — use EventHandler::disable() instead
  • CleanupJob no longer accepts $sendNotifications — events always fire
  • CleanupStrategy constructor changed from Repository $config to Config $config
  • DefaultStrategy changed from raw array config to typed Config DTO
  • Encryption config values changed from null/false/'default' to enum strings ('none', 'default', 'aes128', etc.)
  • BackupDestinationStatus::getHealthCheckFailure() replaced by getHealthCheckFailures() (collection)

freekmurze and others added 10 commits February 15, 2026 23:38
…, add webhook notification channel, introduce BackupLogger, encryption enums, and new backup command options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix PHPStan: remove unnecessary nullsafe operator before ?? in Notifiable
- Fix null encryption config: use array_key_exists instead of ?? to properly handle null
- Fix test constructor args: pass strings to BackupHasFailed/BackupWasSuccessful instead of domain objects
- Fix encryption tests: use enum string values instead of ZipArchive integer constants
- Fix event dispatch assertions: events are now always dispatched, --disable-notifications only suppresses notification handling
- Fix EventHandler static state leak: reset EventHandler::enable() in TestCase setUp
- Fix file inclusion test: clear default excludes that conflict with fake storage path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Lower PHP requirement from ^8.5 to ^8.4 (no 8.5-only features used)
- Add PHP 8.4 to CI test matrix, run PHPStan on 8.4
- Fix backup tests: base_path() in testbench resolves inside vendor/,
  causing all files to be excluded by the vendor exclude rule. Use
  stubs directory as file source instead.
- Update UnhealthyBackupWasFoundTest to match v10 notification format
  where failure details appear directly in content

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The ConsoleOutput class was replaced by BackupLogger in v10,
but the test file was left behind.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@freekmurze freekmurze changed the title v10: Breaking changes for PHP 8.5 and Laravel 12 v10: Breaking changes for PHP 8.4 and Laravel 12 Feb 17, 2026
@freekmurze freekmurze merged commit 22bbe0c into main Feb 17, 2026
7 checks passed
@freekmurze freekmurze deleted the v10 branch February 17, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant