laravel/framework v13.20.0 → v13.21.1

Release v13.21.1 is a compact feature-and-fixes pass on top of v13.20.0. It adds a few developer-facing attributes and validation conveniences, extends the image API, and clears up several edge cases in strings, queues, Redis, and console behavior.

What's new

  • Image output support now covers png, gif, avif, and bmp with fluent methods on Image::toPng(), toGif(), toAvif(), and toBmp(). The image component also now maps AVIF correctly when resolving file extensions, so AVIF outputs get the right extension instead of falling back to .bin (#60713).
  • Adds a base64 validation rule for RFC 4648-style base64 input checks (#60808, #60813).
  • Adds a native #[RouteKey] class attribute for Eloquent models, so you can declare route model binding keys like slug or uuid directly on the model instead of overriding getRouteKeyName() (#60841).
  • Introduces a #[RequestAttribute] contextual attribute, letting controllers resolve request attributes directly into typed parameters instead of pulling them out of the request manually (#60847).
  • Application::configure() now has an extension point for the application builder it uses, which lets subclasses provide their own builder without replacing the whole configure flow (#60848).

Breaking changes

  • Model::resolveClassAttribute() now includes the property name in its cache key. This separates object and property lookups for the same class attribute, which fixes collisions such as #[Table] versus #[Table(timestamps: false)] and changes the cached behavior for models affected by that overlap (#60815).

Fixes

  • Str::wordWrap() now handles multibyte strings correctly instead of counting bytes and potentially splitting UTF-8 characters (#60814).
  • Hub::pipe() now throws a clear InvalidArgumentException when a named pipeline does not exist, instead of surfacing a TypeError (#60802).
  • LogManager::forgetChannel() now handles enum channel names the same way the other channel APIs do (#60801).
  • Queue::createPayload() now includes the job’s display name and queue in InvalidPayloadException messages (#60799).
  • doesntExpectOutput() and doesntExpectOutputToContain() now correctly fail when the unexpected output is "0" (#60816).
  • RedisTaggedCache::decrement() now normalizes enum keys the same way increment() does (#60821).
  • Concurrency task exception reconstruction now preserves falsey constructor arguments like 0, false, and "" (#60822).
  • The serve command now parses host and port values correctly for hostnames and IPv4 addresses such as localhost:8888 and 127.0.0.1:8888 (#60828).
  • Question-mark operators in Grammar::whereColumn() are now escaped the same way they already were in whereBasic(), which avoids PDO treating them as placeholders in joins and similar queries (#60832).
  • JSON:API resources no longer run dead nested relationship compilation code that had no effect on the response (#60829).
  • The lost-connection detector now recognizes an additional Azure Flexible Postgres connection error pattern (#60819).

Other notable changes

  • The Image facade is now included in the default aliases and in the facade docblock workflow, so Image::... is available more naturally in places like Tinker and stays documented in sync (#60795, #60784).
  • illuminate/image now has its license, workflow, .gitattributes, and package suggestions aligned with the rest of the Illuminate subsplit packages (#60824).
  • illuminate/concurrency has been added to the subsplit and release automation (#60836).
  • Carbon test-time cleanup continues in the test suite (#60793).
  • A handful of docblock, assertion, and style cleanups landed across the framework (#60782, #60790, #60791, #60806, #60807, #60809).
  • Install-nightly workflow coverage now checks Windows as well as Linux (#60772).

Contributors

@Tresor-Kasenda @lucasmichot @marekmiklusek @jackbayliss @taylorotwell @axlon @alizadeh7091 @cosmastech @boris-glumpler @daffa-aditya-p @27pchrisl @nimnaherath @ipiner @Button99 @Amirhf1 @aialvi @lazerg