Laravel 13.21 adds a #[RouteKey] class attribute for customizing route model binding on Eloquent models, a base64 validation rule, a #[RequestAttribute] contextual attribute for injecting request attributes, and PNG, GIF, AVIF, and BMP output support in the Image component. The Laravel team tagged v13.21.0 and v13.21.1 on July 21, 2026; the patch tag only bumps the framework's version constant, so the two are covered together here.

  • #[RouteKey] attribute for Eloquent route model binding
  • New base64 validation rule
  • #[RequestAttribute] contextual attribute
  • PNG, GIF, AVIF, and BMP output formats for the Image component
  • Customizable application builder and an illuminate/concurrency subsplit

What's New

#[RouteKey] Attribute for Eloquent Models

Customizing the column used for route model binding has always meant overriding getRouteKeyName() on the model. Following the pattern set by #[ObservedBy] and #[ScopedBy], models can now declare the route key with a class attribute instead:

use Illuminate\Database\Eloquent\Attributes\RouteKey;

#[RouteKey('slug')]

class Post extends Model

{

// ...

}

With the attribute in place, implicit route model binding resolves Post by its slug column, and getRouteKeyName() falls back to the primary key when no attribute is present. Contributed by @nimnaherath in #60841.

base64 Validation Rule

A base64 rule joins the validator's string format checks, filling a gap that libraries like Zod already cover. The rule verifies that a value is a valid RFC 4648 Base64 string:

$request->validate([

'signature' => ['required', 'base64'],

]);

The check requires a canonical encoding: the value must decode in strict mode and re-encode to the exact same string, so padding mistakes and stray characters fail validation. Contributed by @lucasmichot in #60808.

#[RequestAttribute] Contextual Attribute

Middleware often stashes resolved objects on the request's attribute bag, a tenant or organization resolved from an API key, for example. Pulling those back out means calling $request->attributes->get() and type-hinting by hand. The new #[RequestAttribute] contextual attribute injects the value directly into a resolved parameter:

use Illuminate\Container\Attributes\RequestAttribute;

class InventoryController

{

public function index(#[RequestAttribute('org')] Organization $org)

{

return $this->inventoryService->getForOrg($org);

}

}

Contributed by @cosmastech in #60847.

More Output Formats for the Image Component

The Image component introduced in Laravel 13.20 could only convert to WebP, JPG, and JPEG through its fluent methods, even though the bundled Intervention Image encoders support more. This release adds toPng(), toGif(), toAvif(), and toBmp():

use Illuminate\Support\Facades\Image;

Image::fromUpload($request->file('avatar'))

->cover(400, 400)

->toAvif()

->quality(80)

->store('avatars');

The change also fixes Image::extension(), which was missing the image/avif MIME mapping and would have produced a .bin extension for stored AVIF output. Contributed by @Tresor-Kasenda in #60713.

Customizable Application Builder

Application::configure() previously hardcoded the ApplicationBuilder class, so packages extending Laravel's Application had to override the whole method to swap it out. A protected static $applicationBuilder property now lets subclasses provide their own builder class while keeping the existing API. See #60848.

Concurrency Subsplit

The Illuminate\Concurrency component now has its own read-only subsplit, joining the other Illuminate components published as standalone packages. See #60836.

Other Fixes and Improvements

  • Database transaction rollback callbacks now fire correctly (#60777), and a new lost connection message is detected for automatic reconnects (#60819)
  • Question marks are escaped in Grammar::whereColumn() (#60832)
  • InvalidPayloadException messages now include the job name and queue (#60799)
  • Passing an enum to LogManager::forgetChannel() no longer throws a TypeError (#60801), and RedisTaggedCache::decrement() handles enum keys (#60821)
  • Str::wordWrap() handles multibyte strings correctly (#60814)
  • Contextual attribute caching no longer collides across properties of the same class (#60815), and falsey concurrency exception parameters are preserved (#60822)
  • Fixed host port parsing in the serve command (#60828) and an undefined index in Pipeline\Hub::pipe() (#60802)

References