Exciting New Features in Laravel 11

Abu Sayed
7 min readFeb 28, 2024

--

Laravel 11, the latest major release of the popular PHP framework, introduces some exciting improvements that make building robust, scalable web applications faster and easier. In this post, we’ll explore some of the most noteworthy new features, changes, comparison of the pros and cons of different kinds of implementations and approaches and examples.

Exciting New Features in Laravel 11

The Application Bootstrap File

One of the biggest changes in Laravel 11 is the revamping of the bootstrap/app.php file. This file now serves as the main entry point and configuration file for your application. Instead of configuring routing, services, and more in separate files, you can now do it all in app.php.

return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: DIR.'/../routes/web.php',
commands: DIR.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();

This provides a code-first way to configure your application’s core behavior in a single location. Some key things you can now configure in app.php include:

  • Routing — Easily define your route files for web, CLI, and health check endpoints.
  • Middleware — Customize middleware behavior and pipeline order.
  • Service Providers — Manually register providers if needed.
  • Error Handling — Configure custom exception and error handling.

Overall, this new structure makes it faster to configure and bootstrap a new Laravel app.

Streamlined Service Providers

In previous versions of Laravel, new applications included several default service providers out of the box for authentication, validation, routing, and more.

Laravel 11 takes a more minimal approach. Now there is only a single AppServiceProvider by default. The responsibilities of the other providers have been moved into the framework itself or can be handled in your AppServiceProvider if needed.

For example, you can manually register event listeners, route model bindings, policies, and gates directly in AppServiceProvider now. This reduces clutter and allows you to only add what you actually need for your application.

public function register() 
{
$this->app->singleton(UserRepository::class, function () {
//
});
}

public function boot()
{
// Register Auth Gates
Gate::define('update-post', [PostPolicy::class, 'update']);

// Register Model Bindings
Route::model('user', User::class);
}

This streamlined service provider structure simplifies bootstrapping a new app and helps avoid unnecessary bloat.

Opt-In APIs and Broadcasting

The api.php and channels.php routes files are no longer included by default. Since many apps don’t need API or websocket/broadcasting routes, these are now optional.

You can easily add them when needed using Artisan commands:

php artisan install:api
php artisan install:broadcasting

This allows you to start with a leaner application structure and opt-in to more advanced routing as your app evolves.

Unified Middleware Handling

In previous Laravel releases, the HTTP kernel app/Http/Kernel.php class handled configuring the global middleware pipeline. This added some complexity when trying to customize middleware order and behavior.

In Laravel 11, the kernel has been removed in favor of configuring middleware directly in bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
EncryptCookies::class,
]);

$middleware->api(except: [
'/health',
]);
})

You can now easily customize middleware behavior and pipeline for your web and API routes. Common tasks like excluding middleware for certain routes or appending additional middleware is much simpler without a dedicated kernel class.

Improved Logging

Logging has been improved in Laravel 11 with a new LogManager class that provides a simple interface for configuring logs and writing log messages:

LogManager::configure(basePath('storage/logs'));
LogManager::info('User logged in');

The new LogNotifier class allows you to easily register handlers to send log messages to external services like Bugsnag or Sentry:

LogNotifier::add(
new SentryHandler(Client::make())
);

Logging can also be configured based on environment variables, allowing different logging behavior between dev/prod:

LogManager::configureBasedOnEnvironmentVars();

Overall, Laravel 11 provides a simpler log configuration syntax with improved extensibility.

Ability to Delay Job Execution

The job batching and scheduling capabilities of Laravel’s queues have been improved. Now you can easily delay a job’s execution until a later time using the delay method on a job instance:

ProcessPodcast::dispatch()
->delay(now()->addMinutes(10));

This provides an easy way to handle scheduled tasks and workflows directly within your job classes.

Custom PHPunit Assertions

PHPUnit assertions allow you to express the expected behavior of your application in a clear, concise way. Laravel 11 makes it easy to define your own custom assertions using the new assert helper:

assert('emails.sent', $expectedCount, $actualCount);

Custom assertions improve test readability by allowing you to describe the expected behavior in your application’s domain language.

Console Testing Improvements

Testing Artisan console commands is easier thanks to improved assertion syntax in Laravel 11:

public function test_new_user_command() 
{
$this->artisan('user:new')
->expectsOutput('New user created successfully')
->assertExitCode(0);
}

The new expectsOutput and assertExitCode assertions allow you to easily validate exit codes and output of console commands.

Closure Dispatch Binding

When dispatching jobs in Laravel, it’s common to pass currently authenticated user information or other data along with the job. Normally this involves injecting a class into the job’s constructor.

Now in Laravel 11, you can use closure dispatch binding to share state with a job without modifying its constructor:

use App\Jobs\ProcessPodcast;
use Illuminate\Support\Facades\Auth;
dispatch(function () {
return new ProcessPodcast(...);
})->bind(Auth::user());

This provides a cleaner way to inject runtime data into a job instance before dispatching.

Lazy Collections

Lazy collections allow you to work with extremely large datasets without loading the entire collection into memory at once. Now in Laravel 11, the lazy() method converts a standard collection to a lazy one:

$users = User::all()->lazy();
$paidUsers = $users->filter(fn ($user) => $user->plan === 'paid');

The results are loaded lazily, processing small batches at a time. This enables working with gigantic datasets efficiently.

Improved Rate Limiting

Laravel’s built-in rate limiter is even more powerful in Laravel 11. You can now limit based on dynamic data like route parameters:

RateLimiter::for('uploads', function ($pipe) use ($user) {
return $pipe->perMinute(5)->by($user->id);
});

You can also limit based on arbitrary values besides IPs by passing a Closure:

RateLimiter::for('login', function ($pipe) {
return $pipe->perMinute(10)->by(fn() => $this->auth->user()->id);
});

These improvements allow very customized rate limiting behaviors.

Multiple Mail Drivers

In previous releases, Laravel applications could only have a single configured mail driver. Now in Laravel 11, you can configure and use multiple mail drivers at once:

'mailers' => [
'smtp' => [
'transport' => 'smtp'
],
  'postmark' => [
'transport' => 'postmark'
],
],

Then specify which to use per mailable class:

namespace App\Mail;
use Illuminate\Mail\Mailable;class OrderShipped extends Mailable
{
public $mailer = 'postmark';
}

Support for multiple mailers makes it easy to use different services for transactional vs. marketing email.

Pros and Cons

Here is a comparison of the pros and cons of different kinds of implementations and approaches for the new Laravel 11 features:

The Application Bootstrap File

Pros of the New App.php Approach:

  • More centralized configuration in one place
  • Cleaner code structure without separate kernel files
  • Easier to see all configuration at a glance

Cons of the New App.php Approach:

  • Potential for app.php file to grow very large
  • More difficult to understand for those used to old structure
  • Harder to modify middleware order since it’s in PHP instead of kernel file

Pros of the Old Kernel Approach:

  • Separates concerns into dedicated classes
  • Allows modifying middleware order without touching code
  • Familiar structure for experienced Laravel developers

Cons of the Old Kernel Approach:

  • Configuration spread across several files
  • More files to manage and scroll through

Service Providers

Pros of Streamlined Providers:

  • Less bloat in new app skeleton
  • Forced to be more purposeful about what you register
  • Easier to understand provider responsibilities

Cons of Streamlined Providers:

  • Must manually register common functionality now
  • More decisions required early in app building
  • Potential for misconfiguring or missing key providers

Pros of Old Providers:

  • Registration of most common needs handled automatically
  • Conventions for organizing code established
  • New apps work “out of the box” with reasonable defaults

Cons of Old Providers:

  • Lots of unused providers in most apps
  • Harder to find where services are registered
  • New developers rely on defaults instead of learning

Opt-In Routing

Pros of Opt-In Routing:

  • No unnecessary route files cluttering structure
  • Start with lean base and opt-in later
  • Clearer separation between API and web features

Cons of Opt-In Routing:

  • Easy to forget to add API/broadcasting later if needed
  • Multiple commands required to replicate old structure
  • Can’t rely only on default scaffolding

Pros of Default Routing Files:

  • Works out of the box for common use cases
  • Clear conventions for organizing routes
  • New apps have reasonable starting structure

Cons of Default Routing Files:

  • Many apps don’t need default API and broadcasting
  • Creates clutter in simple applications
  • Harder to understand intended separation of concerns

So in summary, while the new Laravel 11 conventions provide cleaner and more flexible code, they do require more thoughtful configuration for common needs up front. The old approaches had more prescriptive defaults that allowed for faster building at the expense of potential bloat. But overall, both offer reasonable ways to structure Laravel applications.

Example

Here a example of the steps to configure and send email using multiple mail drivers in Laravel 11:

1. Install and configure mail driver packages

Use Composer to install packages for the mail services you want to use, like guzzlehttp/guzzle for Mailgun or wildbit/swiftmailer-postmark for Postmark.

2. Define mail driver connections

In config/mail.php, specify your connections under the mailers config. For example:

'mailers' => [
'smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587),
// ...
],
  'postmark' => [
'transport' => 'postmark',
'token' => env('POSTMARK_TOKEN'),
],
],

3. Create your mailable classes

Generate mailable classes as normal with make:mail. Be sure to specify which mailer each one should use:

public $mailer = 'postmark';

4. Queue and send the mailables

Queue the mailables as needed in your app logic, using your preferred queue driver:

NotificationMailer::dispatch($user); 
ReminderMailer::dispatch($customer)->delay(now()->addMinutes(30));

5. Configure mail defaults

If desired, set default mailers in config/mail.php:

'defaults' => [
'mailer' => 'smtp',
'from' => [email protected]',
],
],

6. Send mail

Use the Mail facade to send mail. It will use the configured mailer and defaults:

Mail::to($user)->send(new OrderConfirmation($order));

That covers the main steps to start sending mail through multiple drivers in Laravel 11! The key is defining connections, assigning per mailable class, queuing, and using the Mail facade.

Conclusion

Laravel 11 contains many smaller improvements as well, like:

  • Model factory classes
  • Illuminate/Testing namespace
  • Custom Blade compiler extensibility
  • Improved event:list Artisan command

Overall, the improvements in Laravel 11 help you build robust, enterprise-grade applications faster and with cleaner code. The upgrades to logging, rate limiting, queues, mail, and testing demonstrate Laravel’s continued evolution as a mature framework.

So give Laravel 11 a try today on your next project! The intuitive API and developer experience make it a joy to use for building modern web applications.

--

--

Abu Sayed
Abu Sayed

Written by Abu Sayed

Bangladeshi Full Stack Web Dev, Sys Admin & DevOps Engineer. Skills: Data analysis, SQL, Unity, C#. Python, PHP & Laravel. Me on: bd.linkedin.com/in/imabusayed

No responses yet