Changelog
New updates and improvements to Laravel’s open source products.
August 2025
Laravel Framework 12.x
Add withHeartbeat
Method to LazyCollection
Pull request by @JosephSilber
1$collection2 ->withHeartbeat(CarbonInterval::minutes(5), function () {3 // ...4 })5 ->each(function ($item) {6 // ...7 });
The new withHeartbeart
method allows you to run a callback at regular time intervals while the collection is being lazily enumerated, particularly useful for long-running processes.
Add toPrettyJson
Method
Pull request by @WendellAdriel
1$collection = collect([1,2,3]);2 3// Instead of this:4$collection->toJson(JSON_PRETTY_PRINT);5 6// You can now do this:7$collection->toPrettyJson();
Add allowedUrls
Through preventStrayRequests
Pull request by @rabrowne85
1Http::allowStrayRequests([2 'http://127.0.0.1:13714/*',3]);
The Http::allowStrayRequests
method now accepts an argument that allows you to specify URLs that tests are allowed to send requests to when using Http::preventStrayRequests
.
Add "Copy as Markdown" Button to Error Page
Pull request by @mpociot
There is now a "Copy as Markdown" button on the Laravel exception page. When clicking this button, a markdown representation of the exception is copied to the users clipboard, which can then be used for AI agents/LLMs.
Add New mergeVisible
, mergeHidden
and mergeAppends
Methods
Pull request by @jonerickson
1protected function initializeTwoFactorAuthentication(): void 2{ 3 $this->mergeHidden([ 4 'app_authentication_secret', 5 'app_authentication_recovery_codes', 6 ]); 7 8 $this->mergeCasts([ 9 'app_authentication_secret' => 'encrypted',10 'app_authentication_recovery_codes' => 'encrypted:array',11 ]);12}
Additional attribute helper methods added to Eloquent models for merging visibility-related arrays, bringing them in line with existing helpers like mergeCasts
, mergeFillable
, and mergeGuarded
.
Add Arr::push()
Pull request by @inxilpro
1if ($this->hasChanges($data)) {2 Arr::push($result, 'pending.changes', $data);3}
A new Arr
method that allows you to push something to an array if the array exists, or initialize it to an empty array and then push to it if it doesn't.
Inertia
Introduction of the Form
Component
Pull request by @pascalbaljet
1<script setup> 2import { Form } from "@inertiajs/vue3"; 3</script> 4 5<template> 6 <Form action="/users" method="post"> 7 <input type="text" name="name" /> 8 <input type="email" name="email" /> 9 <button type="submit">Create User</button>10 </Form>11</template>
A new <Form>
component that behaves much like a classic HTML form and simply allows Inertia to intercept the network call on form submission. This new component greatly reduces the boilerplate needed to create a form with Inertia.
Support for Passing Wayfinder Objects to Router Methods
Pull request by @pascalbaljet
1import UserController from "@/actions/App/Http/Controllers/UserController"; 2 3// Regular visits 4router.visit(UserController.store()); 5 6// Prefetching 7router.prefetch(UserController.index()); 8router.getPrefetching(UserController.index()); 9router.getCached(UserController.index());10router.flush(UserController.index());
Adds support for passing Wayfinder-like objects into router methods instead of specifying the URL and method manually.
Tag-Based Cache Invalidation for Prefetch Requests
Pull request by @pascalbaljet
1// Specify cache tags via the Link component 2<Link href="/users/1" prefetch="hover" :tags="['user', 'profile']"> 3 View Profile 4</Link> 5 6// Or via prefetch method on the route 7router.prefetch( 8 '/users', 9 { method: 'get', data: { page: 2 } },10 { cacheFor: '1m', tags: ['users'] }11)12 13// Flushes all cache entries tagged with 'user'14router.flushByTags(['user'])15 16// Flushes entries tagged with 'user' OR 'product'17router.flushByTags(['user', 'product'])18 19// Flush via visit20router.visit('/users', {21 invalidate: ['user']22})23 24// Flush via useForm helper25form.post('/users', { invalidate: ['users'] })
Introduces tag-based cache invalidation for prefetch requests. This enables better control over the prefetch cache without having to flush everything.
Support for Passing Custom Component to as
Prop of Link
Component
Pull request by @pascalbaljet
1<Link as={CustomButton} method="post" href="/user" data={{ test: "data" }}>2 Custom Component with Data3</Link>
The Inertia Link
component now supports custom components instead of just HTML tags such as a
or button
.
Boost
Laravel Boost was released this month! Not only was it just released, it is already aware and up-to-date with the just-released Pest 4 and Filament 4.
Add enabled
Option to Config
Pull request by @xiCO2k
Adds a config('boost.enabled')
option to allows users to specifically enable/disable Boost in certain scenarios outside of environment constraints.
Update Pint Guideline to Use --dirty
Flag
Pull request by @yitzwillroth
Updates Boost guidelines to prefer the usage of Pint with the --dirty
flag for cleaner diffs and PRs.
React + Vue Starter Kits
Migrate useForm
to New Inertia Form
Component
Pull request by @joetannenbaum
1import { Form } from "@inertiajs/react";2 3export default function Login() {4 return (5 <Form action="/login" method="post">6 {/* Form fields */}7 </Form>8 );9}
Reduces the boilerplate for all forms in the starter kits by replacing useForm
with the new Inertia Form
component.
Replace Ziggy With Wayfinder
Pull request by @joetannenbaum
1import AuthenticatedSessionController from "@/actions/App/Http/Controllers/Auth/AuthenticatedSessionController"; 2import { Form } from "@inertiajs/react"; 3 4export default function Login() { 5 return ( 6 <Form {...AuthenticatedSessionController.store.form()}> 7 {/* Form fields */} 8 </Form> 9 );10}
Removes Ziggy from the starter kits and replaces it with the current version of Laravel Wayfinder, bringing end-to-end type safety to your routes.
100% Baseline Test Coverage
Pull request by @JaavierR
Adds the missing feature tests so that fresh projects start with 100% test coverage.
Sail
Allow Sail to Run Pest 4 Browser Tests
Pull request by @rogerio-pereira
Docker configuration updates to allow you to run Pest 4 browser tests in Sail.
VS Code Extension
Add DDEV Support
Pull request by @damms005
Adds proper support for DDEV, Docker-based PHP environments.
Add Support for Custom View Extensions
Pull request by @ryangjchandler
The extension now recognizes custom registered view extensions such as .blade.sh
or .blade.ts
and will now autocomplete and link correctly to these files.
Support for Configs in Subfolders
Pull request by @N1ebieski
The extension now supports configs in nested subfolders (e.g. config/foo/bar/baz.php
), providing better autocomplete and linking.
Link Directly to Problem Files
Pull request by @N1ebieski
Now, when the extension warns you about an invalid value, such as a config key, the warning will directly link you to the file where you can fix the issue.
Autocompletion for Route::is
and routeIs
Methods
Pull request by @N1ebieski
Full autocomplete and linking support for the Route::is
and routeIs
methods.
Wayfinder
Introduce Route Utility Types for Improved DX
Pull request by @istiak-tridip
1import type { RouteDefinition } from "@/wayfinder";2 3const sendRequest = (route: RouteDefinition<"post">) => {4 //5};6 7sendRequest(StorePostController());
Utility types are now exported, making them easier to consume if your app requires them.
Support for Providing Default URL Parameters via the Frontend
Pull request by @owenconti
1setup({ el, App, props }) {2 const root = createRoot(el);3 4 setUrlDefaults({5 workspace: props.initialPage.props.workspace.slug6 });7 8 root.render(<App {...props} />);9},
In instances where Wayfinder is unable to determine the proper default URL params as defined by the server, you can now specify them on the client side using setUrlDefaults
.
July 2025
Laravel Framework 12.x
Added Verbose Output for queue:work
Pull requests by @seriquynh & @amirhshokri
1php artisan queue:work --verbose2// App\Jobs\UrgentAction 85 high3// App\Jobs\NormalAction 84 default
With --verbose
, you’ll now see queue names alongside each job and job ID, making multi-queue debugging straightforward and saving you time when tracing issues.
Uri
Implements JsonSerializable
Pull request by @devajmeireles
1echo json_encode(new Uri('/path?x=1'));2// "http://localhost:8000/path?x=1"
This release fixes a serialization bug, properly converting the URI to a string when serializing a larger JSON object that contains the URI as a value.
Added doesntStartWith()
& doesntEndWith()
Str
Methods
Pull request by @balboacodes
1str('apple')->doesntStartWith('b'); // true2str('apple')->doesntEndWith('e'); // false
The inverse of startsWith
/endsWith
, these new methods allow you to fluently test for starting and ending characters in your string.
Closure Support in pluck()
Pull request by @ralphjsmit
1$users->pluck(fn($u) => $u->email, fn($u) => strtoupper($u->name));
You can now dynamically generate keys and values via callbacks. Instead of mapping then plucking, you get a single, flexible method that reduces steps and keeps intent clear.
Pint
Added --parallel
Option
Pull request by @nunomaduro
1./vendor/bin/pint --parallel
By leveraging PHP CS Fixer’s parallel runner, Pint now formats files concurrently. On large codebases that once took minutes, you’ll see results in seconds, speeding up both local workflows and CI pipelines for a clear quality of life win.
Telescope
Migrated to Vite
Pull request by @nckrtl
Telescope’s frontend now uses Vite instead of Mix. Asset builds finish faster, hot-reloads are more reliable, and you benefit from a modern toolchain without changing your workflow.
Octane
FrankenPHP’s File Watcher
Pull request by @kohenkatz
Octane now relies on FrankenPHP’s native file watcher for reloading the server on file changes. This removes the NodeJS dependency and eases the local development process significantly.
Inertia
Reset Form State and Clear Errors with a Single Method
Pull request by @pascalbaljet
1const form = useForm({ name: "", email: "" });2 3// Instead of:4form.reset();5form.clearErrors();6 7// You can now:8form.resetAndClearErrors();
You can now concisely reset all fields and errors in one go, bringing your form back to square one.
Prevent Minifying JavaScript Builds and Test Apps
Pull request by @pascalbaljet
Inertia no longer distributes minified builds, aligning it with the strategy of other popular libraries. This makes debugging more straightforward and allows for local patching if the need arises.
June 2025
Laravel Framework 12.x
Added encrypt()
and decrypt()
String Helper Methods
Pull request by @KIKOmanasijev
You can now chain encrypt()
and decrypt()
directly on a Str
instance, so instead of piping your string through separate encryption calls, you can write:
1$value = Str::of('secret')->encrypt()->prepend('Encrypted: ');2$original = Str::of($value)->decrypt();
This keeps your string-manipulation chains concise (no need to write separate, extra code to handle encryption) and you don’t have to manually wrap a value in encryption calls each time.
Learn more about encrypt
and decrypt
Added broadcast_if()
and broadcast_unless()
Utilities
Pull request by @taylorotwell
You now have two methods for conditional broadcasting in a single call:
1broadcast_if($order->isPaid(), new OrderShipped($order));2broadcast_unless($user->isActive(), new InactiveUserAlert($user));
This replaces multi-line conditionals around broadcast()
and makes your event logic more readable, improving the overall developer experience.
Read the docs about event broadcasting in Laravel
Added --batched
Flag to make:job
Pull request by @hafezdivandari
The php artisan make:job
command now accepts a --batched
option:
1php artisan make:job ProcessPodcast --batched
This command scaffolds the job with the Batchable
trait already applied, so you don’t have to add it manually. It saves you a manual step and ensures consistency.
Learn more about defining batchable jobs
VS Code Extension

Memory Improvements
Pull request by @joetannenbaum
We fixed a memory-leak issue in the extension’s background processes, reducing its long-term footprint and preventing slowdowns during extended coding sessions.
Improved Startup Time
Pull request by @joetannenbaum
Initialization with the VS Code extension now completes in under one second (down from 5–7 seconds) by deferring heavy setup until it’s actually needed. You’ll notice the extension loads almost instantly so you can start building faster.
Get started with the Laravel VS Code extension
Inertia
Allow deepMerge
on Custom Properties
Pull request by @mpociot
When implementing infinite scrolling with Inertia or other paginated data merges, you can now specify a key (matchOn
) to do a deep merge, matching items by ID and replacing or appending as appropriate. This provides greater flexibility, prevents duplicated entries, and keeps your client-side data consistent.
1Inertia::render('Users/Index', [2 'users' => Inertia::deepMerge($users)->matchOn('data.id'),3]);
Learn more in the Inertia docs
Prevent Duplicate Render in React
Pull request by @pascalbaljet
We fixed a React-specific issue in <StrictMode>
where the initial Inertia page would render twice. Now you get a single, clean first render without flicker, improving perceived performance.
Get started with the Laravel + React Starter Kit