Skip to content

Support Laravel 13 - #1487

Open
austinderrick wants to merge 1 commit into
wintercms:wip/1.3from
austinderrick:wip/1.3-laravel-13
Open

austinderrick wants to merge 1 commit into
wintercms:wip/1.3from
austinderrick:wip/1.3-laravel-13

Conversation

@austinderrick

@austinderrick austinderrick commented Jun 1, 2026 •

Copy link
Copy Markdown
Contributor

Depends on wintercms/storm#228 (Storm Laravel 13 support). Until that PR merges, this PR resolves Storm and the three modules through temporary Composer entries. See "Before merging" below.

Builds on #1366 (Laravel 12 support) and moves Winter CMS 1.3 to Laravel 13.

Summary

Laravel 13 was released on 2026-03-17 and requires PHP 8.3. Most of this PR is dependency and CI changes. There is one module code change.

Code change

  • modules/system/classes/VersionManager.php: array_last(array_where(...)) is now Arr::last($histories, fn). Storm no longer defines the global array_last() helper, and symfony/polyfill-php85 defines a native array_last() that takes a single argument, so the old call would break.

Dependency changes

  • Root composer.json: php ^8.2 → ^8.3; laravel/framework ^12.0 → ^13.0; phpunit/phpunit ^11.0 → ^11.5.50. Laravel 13 and Testbench 11 need at least PHPUnit 11.5.50. PHPUnit stays on 11.x because dms/phpunit-arraysubset-asserts and meyfa/phpunit-assert-gd have no PHPUnit 12 release yet.
  • modules/{system,backend,cms}/composer.json: the same php and laravel/framework changes.
  • Temporary entries for CI, which must be removed before merge:
    • winter/storm requires dev-wip/1.3-laravel-13 as 1.3, from a VCS repository for austinderrick/storm.
    • The three modules require dev-wip/1.3-laravel-13, from path repositories that point at the in-repo modules/ directories. The published split packages still require Laravel 12. Composer reports "Source already present", and the CI "Reset modules" step keeps the committed modules.
  • VCS repositories set "no-api": true, so Composer clones them with plain git. CI for pull requests from forks has no GitHub API token.

CI

  • tests.yml: the PHP matrix drops 8.2 and is now ['8.3', '8.4', '8.5']. The JavaScript job moves from PHP 8.2 to 8.3.
  • code-quality.yaml: PHP 8.2 → 8.3.

Before merging

  1. Merge Support Laravel 13 storm#228.
  2. In composer.json, change winter/storm back to dev-wip/1.3 as 1.3 and the three modules back to dev-wip/1.3.
  3. Delete the austinderrick/storm VCS repository and the three path repositories. Keep the pieterocp/phpunit-arraysubset-asserts repository.

If these entries merge, every install of wip/1.3 resolves Storm from a personal fork, and projects created from Winter resolve the core modules from their own modules/ directory, so composer update never pulls module updates. After this PR merges, the subsplit workflow publishes the Laravel 13 module manifests, so the path repositories are no longer needed.

Breaking changes

These are the breaking changes surfaced while upgrading WinterCMS (and a real downstream app) to Laravel 13. Plugin and theme authors should review these.

PHP 8.3 minimum

Laravel 13 requires PHP 8.3+ (the 1.3 / Laravel 12 line allowed 8.2). CI matrices drop 8.2.

Models may not be instantiated while booting (LogicException)

Laravel 13 throws LogicException: The [Model::bootIfNotBooted] method may not be called on model [X] while it is being booted when a model is instantiated during its own boot — i.e. new static, new self, (new self()), self::instance(), or anything that constructs the model (including static::insert() / static::query()) inside that model's boot() or a trait's boot<TraitName>() method.

  • Storm's own ArraySource trait was affected — fixed in Support Laravel 13 storm#228 (datasource setup deferred to first connection resolution).
  • Plugin/model authors: move boot-time instantiation out of the boot cycle. Register it via static::extend(fn ($model) => ...) (runs per instance after construction) or a deferred booted event. (In a real downstream app this hit several model traits that did (new self())->hasRelation(...) / self::instance() validation in boot<Trait>().)

Laravel Debugbar 4 required (Winter.Debugbar)

Laravel 13 requires barryvdh/laravel-debugbar ^4, a significant break for anything integrating with it — fixed for the plugin in wintercms/wn-debugbar-plugin#27:

  • Namespace rebrand: Barryvdh\Debugbar\* → Fruitcake\LaravelDebugbar\* (the Composer package name stays barryvdh/laravel-debugbar). Any code using Barryvdh\Debugbar\Facades\Debugbar, Barryvdh\Debugbar\LaravelDebugbar, Barryvdh\Debugbar\DataCollector\*, etc. must switch to Fruitcake\LaravelDebugbar\....
  • Barryvdh\Debugbar\SymfonyHttpDriver removed (v4 configures its own LaravelHttpDriver).
  • LaravelDebugbar::__construct() now requires (Application $app, Request $request) — resolve via the container, not new LaravelDebugbar($app).
  • php-debugbar's DataCollectorInterface is now typed: collect(): array, getName(): string, getWidgets(): array. Custom collectors must add these return types.
  • The formatDuration() convenience method was removed from php-debugbar's DataCollector base; use $this->getDataFormatter()->formatDuration().
  • php-debugbar no longer bundles a Twig profile collector (DebugBar\Bridge\TwigProfileCollector / NamespacedTwigProfileCollector); guard with class_exists().

Storm container log alias

Storm aliased the 'log' service to Illuminate\Log\Logger, but 'log' is a LogManager. Laravel 13 (and Laravel Debugbar 4's log collector, which type-hints Illuminate\Log\Logger) expose this — resolving Illuminate\Log\Logger returned a LogManager, throwing a TypeError. Fixed in wintercms/storm#228 to alias 'log' to Illuminate\Log\LogManager (matching Laravel core), so Illuminate\Log\Logger autowires to a real Logger.

General Laravel 13 changes

Also review the upstream Laravel 12 → 13 upgrade guide: CSRF middleware renamed VerifyCsrfToken → PreventRequestForgery (deprecated aliases kept); symfony/polyfill-php85 now defines global array_first() / array_last() (single-arg — prefer Winter\Storm\Support\Arr::first() / Arr::last()); Bootstrap pagination view names renamed; down --with-secret handling.

Testing

CI passes on this branch (Ubuntu and Windows, PHP 8.3, 8.4 and 8.5), running against the Storm branch from wintercms/storm#228:

  • system: 323 tests, 0 failures, 29 skipped
  • backend: 250 tests, 0 failures
  • cms: 219 tests, 0 failures
  • JavaScript tests pass on Ubuntu and Windows.

Related Winter CMS Laravel 13 PRs

@coderabbitai

coderabbitai Bot commented Jun 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: e5c0349f-bae8-4b12-b93d-ad0006594aa9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This pull request upgrades Winter CMS to PHP 8.3 and Laravel 13. CI workflows update PHP versions in setup steps and test matrices. Composer manifests across the root project and system, backend, and CMS modules raise PHP requirements from ^8.2 to ^8.3 and Laravel from ^12.0 to ^13.0. Winter module dependencies shift to dev-wip/1.3-laravel-13 branches with repository configurations updated accordingly. Additionally, VersionManager refactors getCurrentVersionNote() to use the Arr::last utility with a type predicate for selecting comment history entries.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Support Laravel 13' directly and clearly describes the main objective of the PR, which is to add Laravel 13 support through version updates across dependencies and CI configurations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@austinderrick
austinderrick force-pushed the wip/1.3-laravel-13 branch 2 times, most recently from f24ee4f to c9c1ba4 Compare June 1, 2026 23:56
@austinderrick

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Move Winter to Laravel 13 (PHP 8.3+): bump the framework and PHPUnit constraints in the root and
module manifests, use Arr::last() in VersionManager, resolve Storm and the modules from the Laravel
13 branches until wintercms/storm#228 merges, and update the CI matrix.
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