Table of Contents
1
Introduction
1.1
Acknowledgements
1.2
The prerequisites
1.3
Laravel loses weight
1.4
bootstrap/app.php: the centraliser
1.4.1
Where the hell are my configuration files?
1.4.2
How to manage providers with Laravel 11 ?
1.4.3
Middleware is missing
1.4.4
50% of routes have also disappeared
1.4.5
Exception handling
1.4.6
New in scheduling
1.5
The return of sqlite
1.6
Laravel Reverb
1.7
On the Artisan side
1.8
Adding the dumpable feature
1.9
The health of your Laravel application
1.10
Doctrine DBAL is no longer needed
1.11
Eloquent Eager Limit package integration
1.12
Improved rate limiting system
1.13
Intelligent rotation of encryption keys
1.14
Automatic password hashing
1.15
The once() helper
1.16
Database Improvements
1.17
Model Casts Improvements
1.18
Laravel Prompt Validation
1.19
Documentation update
1.20
Laravel 11: new default home page for your new projects
1.21
Should I migrate from Laravel 10 to Laravel 11?
1.22
Next version
1.23
Frequently asked questions
1.24
Glossary
1.25
Who am I?
1.26
End
1.27
Introduction
Laravel 11 was released on Tuesday 12 March 2024.
This is obviously a celebration
π for all LaraDevs.
This new version brings its share of new features compared to the previous version.
This ebook aims to give you a quick and effective introduction to the changes in this version.
There's a lot to see and integrate, so let's set off on an adventure together to find out all about it.
Note
I don't claim to know everything about Laravel, and even less about Laravel 11.
I simply want to help the community by synthesising the information available on Laravel 11 that I have found
through my own experience but also in various sources on social networks.
If you notice any errors, inaccuracies or gaps, please let me know so that I can correct them.
Sources
In addition to my own experiments, I've drawn on the work of well-known Laravel experts to back up what I've said.
2
I seriously recommend the Laracasts series by Luke Downing and Jeffrey Way.
Laracasts: What's new in Laravel 11 by Luke Downing
Laracasts: 30 Days to Learn Laravel by Jeffrey Way
In addition, the video of Taylor Otwell from Laracon US 2023, who gave the first elements of Laravel 11.
As far as blogs are concerned, I'd recommend reading :
Laravel News
Laravel Daily
The Laravel Jutsu blog
Benjamin Crozat's blog
I hope you enjoy reading.
3
Acknowledgements
First of all, I'd like to thank my wife and my children for their daily support, without them I'd be nothing. I love you all.
Next, I'd like to thank all the people who reviewed this ebook and gave me their feedback, corrections and
suggestions for improvement.
I'd also like to thank all the readers of this book and everyone in the Laravel community. It's a pleasure to share and
read your contributions to our framework on a daily basis.
And finally, thank you to PHP and all its contributors, thank you to Taylor Otwell and the whole Laravel team for the
pleasure you've given me over the years to be able to work with these wonderful tools that are PHP and Laravel.
4
Prerequisites
From Laravel 11 onwards, it is mandatory to use PHP 8.2.
And that's perfectly normal, because at the time I'm writing this (24 March 2024), PHP 8.1 is at the end of its life and
only has security support left.
Source : PHP official website
5
Laravel loses weight!
Generally speaking, the structure of a Laravel 11 application is lighter than in version 10. The Laravel team has
called this : Slim Skeleton.
Let's take a look at these changes.
For more details, you can of course consult the documentation on this subject.
In this chapter we're going to talk about :
boostrap/app.php
files in the config directory
providers
middleware
routes
exceptions
scheduling
databases and sqlite
6
bootstrap/app.php : the centraliser
This file has been completely reworked to federate a large number of parameters that were previously scattered in
different directories of the application.
It will allow you to customise your routing, middlewares, service providers and other configurations.
I'll talk more about this later.
7
Where the hell are my configuration files?
Yes, when you go to install your new version of Laravel, the
config
directory is going to look a lot lighter than what
you were used to with previous versions of Laravel.
Judge for yourself!
Note
To install the 2 versions used for this test, I used for Laravel 10:
composer create-project --prefer-dist laravel/laravel bookl10 "10.*.*"
For Laravel 11, I first uggraded my version of Laravel Installer as indicated in the Release Note:
compose global require laravel/installer:^5.6
and then a classic :
laravel new bookl11
And voilà!
But let's get back to the subject at hand, the
Here you can see that the :
broadcasting.php
cors.php
hashing.php
sanctum.php
8
config
folder.
view.php
The reason?
Quite simply, the Laravel team found that many of the files usually found in the
edited by you. Basically, it's your fault they've been banned
π€£
Initially, Taylor Otwell had announced at Laracon US that all files in the
config
config
directory were simply never
directory would be removed on a
fresh install (Watch video).
However, it seems that only the least-used files have been banned.
So where have these missing files gone?
Well, they've been integrated directly into the core framework.
And if you need to have them in your application, Laravel now has a new Artisan command:
php artisan config:publish
This command lets you choose which configuration file you want to add to your application so that you can make
changes to it.
For example, if you want to retrieve the
the
9
config
directory.
cors.php
file, simply select it from the list, press enter and you'll find it in
And what if I'm lazy?
A dev has to be lazy
π
On a more serious note, it's possible to be a bit of a brute with the :
php artisan config:publish --all
Why brute?
Because of all the mistakes (not serious ones) that can be made!
10
11
How to manage providers with Laravel 11?
Another difference compared to Laravel 10 is the complete disappearance of the 5 provider files found in Laravel 10
in the
App/Providers
directory. This directory now contains just one file:
You can also see that the
providers
AppServiceProvider.php .
key has simply disappeared from the
In fact, as soon as you create a provider with the command
config/app.php
file.
php artisan make:provider NameOfYourServiceProvider ,
it will automatically be taken into account by Laravel.
It is no longer necessary to register it manually.
Obviously, this is only true if you use the command
php artisan make:provider ... .
If you create your provider manually, you can register it directly in the
12
bootstrap/providers.php
file.
The middleware is missing
Let's continue our tour of inspection of Laravel's directories
π.
Middleware missing from its previous location
If we go to
app/http , we immediately notice compared to Laravel 10 the complete absence of the Middleware
folder.
Let's take a look at how Team Laravel has changed all this, and what new habits you need to adopt to get the hang
of it.
As you'll see, it's not as complicated as all that.
Middleware integrated into the heart of Laravel
To begin with, all the files that were present in
heart of the framework :
13
app/Http/Middleware
in Laravel 10 have been integrated into the
<?php
use Illuminate\Auth\Middleware\Authenticate;
use Illuminate\Auth\Middleware\RedirectIfAuthenticated;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
use Illuminate\Foundation\Http\Middleware\TrimStrings;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Http\Middleware\TrustHosts;
use Illuminate\Http\Middleware\TrustProxies;
use Illuminate\Routing\Middleware\ValidateSignature;
...
You can see that all this middleware is now integrated directly into the heart of the framework in the
Illluminate
directory.
How do you customise the way middleware works?
In middleware, you often had an array like this:
protected $except = [
//
];
which allowed the middleware to be ignored in certain cases. All you had to do was enter the desired value and it
would be ignored.
Under Laravel 11 these customisations will take place in the
Let's take the example of the
Here are its contents:
14
ValidateSignature.php
app/Providers/AppServiceProvider.php
middleware present in Laravel 10.
file.
// With Laravel 10
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [
// 'fbclid',
// 'utm_campaign',
// 'utm_content',
// 'utm_medium',
// 'utm_source',
// 'utm_term',
];
In Laravel 11, we will modify the
boot
method in
app/Providers/AppServiceProvider.php
as follows:
// Since Laravel 11
...
use Illuminate\Routing\Middleware\ValidateSignature;
...
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
ValidateSignature::except([
'utm_campaing',
'utm_source',
'utm_medium',
]);
}
What happens if I create my own middleware?
Firstly, you can create your middleware in the same way as before:
php artisan make:middleware EnsureTokenIsValid
15
Note
I'm using the example provided in the documentation.
Remember that in Laravel 10 you had to register your middleware in the
app/Http/Kernel.php
file.
This file is no longer present in the new structure of Laravel 11.
From now on, you will need to register your custom middleware in the
function.
Here's how to do it:
use App\Http\Middleware\EnsureTokenIsValid;
->withMiddleware(function (Middleware $middleware) {
$middleware->append(EnsureTokenIsValid::class);
})
You now know how to register your middleware in Laravel 11.
16
boostrap/app.php
file in the
withMiddleware
50% of the routes have also disappeared!
Under Laravel 10, in the
routes
directory, we had the routes :
routes
directory, we still have the routes :
api.php
channels.php
console.php
web.php
Under Laravel 11, in the
console.php
web.php
Once again, as the two routes
and
api
channels
are used much less frequently, they have been removed by
default.
Making them reappear in the
routes
directory is very simple and will obviously involve, as you may have guessed,
artisan.
Let's take a look at this now.
php artisan install:api
This command will allow you to :
add the
routes/api.php
launch the
route
create_personal_access_tokens_table
migration
It will also launch the installation of Laravel Sanctum.
By default, Laravel Sanctum is installed. If you would like Laravel Passport instead, simply add the appropriate
option:
php artisan install:api --passport
php artisan install:broadcasting
This command will allow you to :
publish the
add the
config/broadcasting.php
routes/channels.php
configuration file
route
decide whether or not to install Laravel Reverb, which was released at the same time as Laravel 11
17
In the
config/broadcasting.php
while the
redis
file, you can see that the
connections
array has had the
reverb
array added to it,
array has disappeared.
If you choose to install Reverb, the command line will prompt you at the end of the installation to install and build
the Node dependencies.
Note
You can use either
php artisan install:broadcasting
Automatic update of
When you use the
withRouting()
php artisan install:broadcast .
boostrap/app.php
php artisan install:api
function in
or
and
bootstrap/app.php
file
php artisan install:broadcasting
commands, the
will automatically update to take account of the addition of these
routes:
// ...
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__ . '/../routes/web.php',
api: __DIR__ . '/../routes/api.php', // added by php artisan install:api
commands: __DIR__ . '/../routes/console.php',
channels: __DIR__ . '/../routes/channels.php', // added by php artisan install:broadcasting
health: '/up',
)
18
Exception handling
As you will no doubt have noticed, the
app/Exceptions
directory is also one of the victims of the regime imposed on
the skeleton of a new Laravel 11 application.
Error handling will now be managed in the
middleware. This will happen in the
bootstrap/app
withExceptions()
For example, if you want to fill in an element in the
app/Exceptions/Handler.php
file, as we have already seen for routing and
function.
$dontFlash
array, which could be found in
under Laravel 10 :
// Sous Laravel 10
class Handler extends ExceptionHandler
{
/**
* The list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
you can do exactly the same thing in
bootstrap/app.php
as follows:
// Sous Laravel 11
// ...
->withExceptions(function (Exceptions $exceptions) {
//
$exceptions->dontFlash([
'current_password',
'password',
'password_confirmation',
]);
19
New in scheduling
Under Laravel 10, you could set up task scheduling in
app/console/kernel.php
:
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
$schedule->command('model:prune')->daily();
}
// ...
With Laravel 11, the
app/Console
folder has disappeared.
Instead, you'll be able to schedule your tasks directly via the new
use Illuminate\Support\Facades\Schedule;
Schedule::command('model:prune')->daily();
As with Laravel 10, you can run the command :
php artisan schedule:list
to list your current schedules:
20
Schedule
option in the
routes/console.php
file.
The return of sqlite
Laravel 11 introduces a major new feature in terms of databases. By default, the choice of database offered when
installing a new Laravel application is sqlite.
In keeping with the idea of offering the lightest possible application skeleton, the choice has been made to make
sqlite the default.
Why ?
Quite simply because an sqlite database is a single file and the configuration in the
.env
file is a single line.
Let's look at this in detail.
The default choice on installation
Launch a new application with
laravel :
laravel new l11
Once you have answered the first questions about the choice of starter kit, test framework and whether or not to
initialise a git repository, after installing the various packages using
As I said earlier,
sqlite
composer , you will see this appear:
is chosen as the default database engine.
Note that before asking you which database engine you want to choose, Laravel has already :
created the
database/database.sqlite
file
migrated it
made the settings for sqlite in the
21
.env
file
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
But what happens if I choose PostgreSQL, for example?
The installer will detect that the default database has been modified and will ask me if I want to run the migrations
again:
Obviously, if you choose 'yes' this will generate an error as your database is not configured in your
.env
file.
However, Laravel will finish the installation normally.
Note that choosing another database engine does not delete the
database/database.sqlite
file (Laravel version
concerned: 11.0.3).
The
.env
file is updated with the new database engine:
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=l11
DB_USERNAME=root
DB_PASSWORD=
What if I don't want to use a database?
There is no such option. And that's quite normal because Laravel is a complete framework which is geared more
towards working with databases.
However, if you are developing a site without a database based on laravel, you can simply leave sqlite as the
default and then delete the
22
database.sqlite
file as well as all the migrations.
Laravel Reverb
Laravel Reverb was released at the same time as Laravel 11 and was developed by Joe Dixon.
Reverb is a WebSocket server for Laravel applications. It will allow you to easily set up real-time communication
between the client and the server.
Reverb comes with its own Artisan commands. I give details of these new commands in the chapter devoted to
Artisan.
Reverb is an open source project from the Laravel community.
How do you install it?
Simply use the following Artisan command:
php artisan install:broadcasting
Note
You can use either
php artisan install:broadcasting
or
php artisan install:broadcast
Artisan will then ask you if you want to install Reverb, with 'yes' as the default.
It will then ask you for authorisation to install and build the Node dependencies.
23
Once you have agreed to install Reverb and the installation process is complete, you will have access to three new
Artisan commands, which I will describe in detail in the chapter dedicated to Artisan.
Demo of Laravel Reverb
If you'd like to see a concrete example of what Reverb can do for you, take a look at this video presentation by
Christoph Rumpel.
Documentation
To use Reverb, you may find the following documentation useful:
Reverb documentation
Broadcasting documentation
24
From Artisan
Artisan is Laravel's command line tool, and it's a real Swiss army knife for everything.
Let's take a look at what changes version 11 brings to this faithful tool.
Disappearance of the artisan cache:table command
Under Laravel 10, this command was used to generate a migration to create the
cache
Laravel.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration');
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
From now on, with Laravel 11, this migration is integrated into the installation by default.
25
and
cache_locks
tables in
And if your application doesn't contain this migration, as might be the case if you were using Laravel 10 and
migrated to Laravel 11 before generating this table, you can generate it using the
make:cache-table
command.
New php artisan config:publish command
This command adds to your application the config files that have been removed from the new Slim Skeleton.
I won't go back over how it works, as we saw in the chapter Where the hell are my configuration files?.
New php artisan install:api command
This command, like
config:publish , appears because of the implementation of the Slim Skeleton. It adds the API
routes file and launches the installation of Laravel Sanctum or Laravel Passport.
Laravel Sanctum is installed by default; if you want Laravel Passport instead, simply add the appropriate option:
php artisan install:api --passport
New php artisan install:broadcasting command
This command also exists because of Slim Skeleton, I've already explained how it works in the chapter 50% of the
routes have also disappeared!
Note
You can use either
php artisan install:broadcasting
or
php artisan install:broadcast .
New php artisan make commands
Laravel 11 comes with a number of new
make
commands. The number of
make
commands has increased from 25
to 35. However, a number of them (6) replace other artisan commands and centralise them under the
command. For example,
php artisan make:queue-table
replaces
make
php artisan queue:table .
So these 6 commands will not really be considered as new commands but simply as a better organisation of the
existing artisan commands.
The new artisan make commands are
class , enum , interface
and
trait .
php artisan make:cache-table
This command replaces the artisan cache:table command. It creates the migration needed to create the
cache_locks
26
tables.
cache
and
php artisan make:class
This new command creates the skeleton of a new PHP class. The mandatory argument is the name of the class.
If you want to store your classes in a specific folder and not leave them at the root of
app , simply specify the path
when choosing the class name.
The main options currently available are :
-i
or
--invokable : Artisan will generate a class with a single method.
f
or
--force : Artisan will generate your class, but only if the class already exists.
Examples:
php artisan make:class Services/Starlink
Artisan will create a class in
app/Services/Starlink.php .
<?php
// app/Services/Starlink.php
namespace App\Services;
class Starlink
{
/**
* Create a new class instance.
*/
public function __construct()
{
//
}
}
It is perfectly possible to omit the class name:
php artisan make:class
Artisan will then ask you for the name of the class you want to create.
Similarly, you can request an invokable class with the
php artisan make:class -i
or
php artisan make:class Services/Starlink -i
This will give you the following class skeleton:
27
__invoke()
method:
<?php
namespace App\Services;
class Starlink
{
/**
* Create a new class instance.
*/
public function __construct()
{
//
}
/**
* Invoke the class instance.
*/
public function __invoke(): void
{
}
}
php artisan make:enum
This command will allow you to create the skeleton of an
The returned code will be a simple empty Enum class:
<?php
namespace App;
enum role
{
//
}
28
enum
class easily.
If you want to store your classes in a specific folder and not leave them at the root of
app , simply specify the path
when choosing the name of the Enum :
php artisan make:interface
As with
class
and
enum , Artisan now lets you create your own interface skeletons.
php artisan make:interface Interfaces/StarlinkCustomersListInterface
This will generate the following code in
app/Interfaces/StarlinkCustomersListInterface.php
:
<?php
namespace App\Interfaces;
interface StarlinkCustomersListInterface
{
//
}
For interface creation, only the
-f
or
--force
option is available, to create your interface by overwriting any
existing interface of the same name.
php artisan make:notifications-table
Replaces the
php artisan notifications-table
command
php artisan make:queue-batches-table
Replaces
php artisan queue:batches-table
command
php artisan make:queue-failed-table
Replaces
29
php artisan queue:failed-table
command
php artisan make:queue-table
Replaces
php artisan queue:table
command
php artisan make:session-table
Replaces
php artisan session:table
command
php artisan make:trait
As with
class , enum
and
interface , Artisan now lets you create templates for your traits.
php artisan make:trait Traits/HasRoles
This command will generate the following code in
app/Traits/HasRoles.php :
<?php
namespace App\Traits;
trait HasRoles
{
//
}
For creating traits, only the
-f
or
--force
option is available, to create your trait by overwriting any existing trait
of the same name.
New php artisan pest commands
If you've been following the news around Laravel 11 over the last few months, you may have seen this poll from
Taylor Otwell where he asked which test engine should be included by default in Laravel 11 between PestPHP and
PHPUnit :
30
Pest won with 58% of the votes from over 6,000 participants.
So it was only natural that PestPHP should become Laravel's default testing framework. This led the Laravel team
to create two new commands for this testing framework.
php artisan pest:dataset
As a reminder, datasets in PestPHP are defined as follows:
With datasets, you can define an array of test data and Pest will run the same test for each set automatically.
This saves time and effort by eliminating the need to repeat the same test manually with different data.
So the command
php artisan pest:dataset Satellites
tests/Datasets/Satellites.php
will generate a dataset file under
which will look like this:
<?php
dataset('satellites', function () {
return ['satellite A', 'satellite B'];
});
Il ne vous restera plus qu'à définir vos jeux de données.
For more information on DataSets, please refer to the documentation on the PestPHP site.
php artisan pest:test
Obviously, the second command we'll find for Pest is the generation of a test. By default, using this command, your
new test will be saved in the
tests/Features
folder.
php artisan pest:test Launch
This will generate the code below in
31
tests/Features/Launch.php
:
<?php
it('has launch page', function () {
$response = $this->get('/launch');
$response->assertStatus(200);
});
If you want to create a unit test, simply tell PestPHP :
php artisan pest:test Signal --unit
which will generate the following code in
tests/Unit/Signal.php
:
<?php
test('signal', function () {
expect(true)->toBeTrue();
});
New php artisan reverb commands
The coordinated release of Laravel 11 and Reverb brings the appearance of 3 new Artisan commands dedicated to
Reverb. These commands will only be available if you install Laravel Reverb via the command
install:broadcasting .
php artisan reverb:install
This command will allow you to install the necessary dependencies for Reverb.
php artisan reverb:start
This will launch the Reverb server.
The following options can be passed to it:
--host the IP address associated with the server
--port the port on which the server should listen
--hostname The hostname from which the server can be accessed
32
php artisan
--debug Displays debug messages in the terminal. Disabled by default.
If you do not specify any options, Reverb will start at the following address and ports:
0.0.0.0:8080 .
php artisan reverb:restart
According to the documentation:
Since Reverb is a long-running process, changes to your code will not be reflected without restarting the
server via the
The
reverb:restart
reverb:restart
Artisan command.
command ensures all connections are gracefully terminated before stopping the server.
If you are running Reverb with a process manager such as Supervisor, the server will be automatically
restarted by the process manager after all connections have been terminated
This command has no special options.
33
Laravel Dumpable
It is possible to use the
dump()
and
dd()
chained methods in many Laravel classes.
For example, it is possible to do
// ...
User::where('created_ad', '<', now()->subYear(1))->dump()->get();
// Variant with dd()
User::where('created_ad', '<', now()->subYear(1))->dd()->get();
// ...
to check the content of your request.
These methods were implemented in each of the classes where it was possible to call these functions.
Today, Laravel 11 goes one step further. It provides a feature called
dumpable
which not only makes it possible to
lighten the code base of Laravel by factoring these functions in a single place, which is an excellent development
practice, but it also allows you to add these two functions
dd
and
dump
to any of your classes.
All you have to do is call the trait in question.
Let's take a simple example to illustrate this new possibility.
Here's an imaginary class that measures the downstream and upload speeds of a Starlink connection.
34
<?php
namespace App;
class StarlinkMeasuringSpeed
{
protected int $downloadDebit;
protected int $uploadDebit;
protected string $testStatus;
/**
* Create a new class instance.
*/
public function __construct()
{
$this->testStatus = 'KO';
$this->downloadDebit = 0;
$this->uploadDebit = 0;
}
private function measuringDownload()
{
$this->downloadDebit = rand(60, 250);
}
private function measuringUpload()
{
$this->uploadDebit = rand(10, 50);
}
public function runInternetSpeedTest()
{
$this->measuringDownload();
$this->measuringUpload();
$this->testStatus = 'OK';
return $this;
}
}
The following code can be used to display the states of this class:
35
<?php
use App\Models\User;
use App\StarlinkMeasuringSpeed;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$starlinkDebit = new StarlinkMeasuringSpeed();
dump($starlinkDebit);
$result = $starlinkDebit->runInternetSpeedTest();
dump($result);
});
The output will look like this:
Now let's modify our class to add the
36
dumpable
trait.
<?php
namespace App;
use Illuminate\Support\Traits\Dumpable;
class StarlinkMeasuringSpeed
{
use Dumpable;
protected int $downloadDebit;
protected int $uploadDebit;
protected string $testStatus;
/**
* Create a new class instance.
*/
public function __construct()
{
$this->testStatus = 'KO';
$this->downloadDebit = 0;
$this->uploadDebit = 0;
}
private function measuringDownload()
{
$this->downloadDebit = rand(60, 250);
}
private function measuringUpload()
{
$this->uploadDebit = rand(10, 50);
}
public function runInternetSpeedTest()
{
$this->measuringDownload();
$this->measuringUpload();
$this->testStatus = 'OK';
return $this;
}
37
}
By using the
dumpable
trait, we get the same result as before, but with lighter, smoother code thanks to the ability
to chain commands:
<?php
use App\Models\User;
use App\StarlinkMeasuringSpeed;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$starlinkDebit = new StarlinkMeasuringSpeed();
$starlinkDebit->dump()->runInternetSpeedTest()->dump();
});
Here is the output generated by this code:
The result is similar but the code is more readable.
As I mentioned earlier, the
dumpable
line offers both
If we modify our example slightly like this :
38
dump
and
dd .
<?php
use App\Models\User;
use App\StarlinkMeasuringSpeed;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$starlinkDebit = new StarlinkMeasuringSpeed();
$starlinkDebit->dd()->runInternetSpeedTest()->dump();
});
then the script execution will stop with the dump and die of course :
Obviously, this is a very simple example, but its sole purpose is to show you how this new Trait works.
39
Health
Laravel 11 natively provides a route for checking the health of your application. By default, this route is connected to
the
/up
url.
When you go to this address, by default you'll see something like this:
The
routes/app.php
file declares the
up
route via the
withRouting
function in the
vendor/laravel/framework/src/Illuminate/Foundation/Configuration/ApplicationBuilder.php
the
buildRoutingCallback
file, which in turn calls
function:
protected function buildRoutingCallback(?string $web,
?string $api,
?string $pages,
?string $health,
string $apiPrefix,
?callable $then)
{
return function () use ($web, $api, $pages, $health, $apiPrefix, $then) {
// ...
if (is_string($health)) {
Route::middleware('web')->get($health, function () {
Event::dispatch(new DiagnosingHealth);
return View::file(__DIR__.'/../resources/health-up.blade.php');
});
}
// ...
};
}
You can see that this will trigger a
DiagnosingHealth
event in which you can place your logic for checking the
health of your application. Next, this function will return the
health-up.blade.php
view, which displays the little
message shown above by dynamically calculating the response time between the start of the request and its
display.
40
DBAL Doctrine is no longer required
Before Laravel 11
Before laravel 11, there were some cases where you needed to install the :
composer require doctrine/dbal
For example, to
to modify a column in your SQLite database
rename columns in older databases MySQL < 8.0.3, MariaDB < 10.5.2, SQLite < 3.25.0
delete columns in a SQLite < 3.35.0 database
rename indexes with an SQLite database
Source : Documentation Laravel 10 on migrations
Since Laravel 11
Since Doctrine/DBAL is no longer a dependency of Laravel, it is no longer necessary to install it.
Source : Upgrade guide for Laravel 11
41
Integration of the Eloquent Eager Limit package
Laravel 11 natively embeds in its core the Eloquen Eager Limit package from Jonas Staudenmeir.
This will make it possible to limit the number of fast loading results per parent and to use the following code:
$users = User::with(['posts' => function ($query) {
$query->latest()->limit(10);
}])->get();
and get the last 10 posts from each user.
Without this implementation and without this package in previous versions of Laravel, only the first user had his
posts returned.
For a more visual demonstration, I invite you to watch the video that Luke Downing made on the subject.
42
Improved rate limiting system
Laravel includes powerful and customisable rate limiting services that you can use to restrict the amount of traffic
for a given route or group of routes.
Until version 10 of Laravel, you could only set limiters down to a granularity of one minute.
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});
With version 11 of Laravel, it is now possible to use limiters for durations shorter than a minute and therefore up to a
second:
RateLimiter::for('global', function (Request $request) {
return Limit::perSecond(10)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});
43
Intelligent rotation of encryption keys
When Laravel is installed, your encryption key is defined for you in the
APP_KEY
variable in your
.env
file.
If you were to change this key with Laravel 10 and previous versions, all authenticated user sessions would be
disconnected from your application. This is because all cookies, including session cookies, are encrypted by
Laravel. Furthermore, it will no longer be possible to decrypt data that has been encrypted with your old encryption
key.
Laravel 11 introduces the possibility of defining an additional variable in your
.env
file under the name
APP_PREVIOUS_KEYS .
You can then place all your previous encryption keys in this variable, separating them by a comma:
APP_KEY="base64:XLMgslk6a16W7sRRUa4iASJzHGY2GUmMPHyeoEk7y7E="
APP_PREVIOUS_KEYS="base64:gJ2KpQl5E+I5IOTvRuBtP5/Wl3Q9ostuc/dBGBOjqj0=,base64:+wW3AymZXPQwgBI1AZnXps2G5cqmAVldHa
When you set this environment variable, Laravel will always give priority to the "current" encryption key when
encrypting values.
However, if when decrypting values, Laravel is unable to decrypt with the current key, it will then try with all the
other keys defined in the
44
APP_PREVIOUS_KEYS
variable.
Re automatic password hashing
Stephen Rees-Carter is behind this addition. From now on, if you increase the value of
.env
BCRYPT_ROUNDS
in your
file to a higher value.
Your users' passwords will be hashed again, taking this new parameter into account, the next time they log in.
User hash before increasing the
Hash users after increasing
BCRYPT_ROUNDS
value
BCRYPT_ROUNDS .
The user fred has logged out and logged back in. Only his password hash has been changed. The happytodev
user's password will be "re-hashed" the next time he logs in.
How do I deactivate this feature?
This feature can be disabled by setting the
45
rehash_on_login
key to
false .
The once() helper
Laravel 11 introduces this new helper, which is very practical.
The
once()
helper will cache the result of the callback passed to it for the duration of the current request's
lifecycle.
Here are two examples:
Simple use in a function
function random(): int
{
return once(function () {
return random_int(1, 1000);
});
}
random(); // 123
random(); // 123 (cached result)
random(); // 123 (cached result)
Even if you call the
random()
function several times, the result remains the same. The first call executes the
function and subsequent calls use the cache generated during the first call to the function.
Note
This example is taken from the official Laravel documentation.
Use in a class
For this example, I've adapted the example code provided in the documentation to better reflect the impact of the
once()
helper with different class instances.
<?php
namespace App\Services;
class NumberService
{
protected $randomNumber;
public function getRandomNumber()
{
$this->randomNumber =
return $this;
}
}
46
once(fn () => random_int(64, 1024));
<?php
use App\Services\NumberService;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$ns1 = new NumberService();
dump($ns1->getRandomNumber()); // 128
dump($ns1->getRandomNumber()); // 128 (cached result)
$ns2 = new NumberService();
dump($ns2->getRandomNumber()); // 861
dump($ns2->getRandomNumber()); // 831 (cached result)
});
The result of these calls to the
getRandomNumber
function on two different instances of the
NumberService
class is
as follows:
As far as classes are concerned, we can see that the caching done by the
once()
helper is done per instance of
the class.
I've kept these examples deliberately simple so as not to make this book too long.
If you'd like to see a more concrete implementation of the
Downing.
Documentation for the
47
once()
helper
once()
helper, I suggest you watch this video by Luke
Database improvements
This new version of Laravel also brings changes that may not be directly visible in your application, but which will be
noticeable in terms of improved performance and user experience.
Improved performance when testing with in-memory
databases
With contributions from Anders Jenbo
According to the documentation:
Laravel 11 offers a significant speed boost when using the :memory: SQLite database during tests. To do this,
Laravel maintains a reference to PHP's PDO object and reuses it across connections, often halving total test
execution time.
Improved support for MariaDB
With contributions from Jonas Staudenmeir and Julius Kiekbusch
In previous versions of Laravel, it was possible to use the MariaDB database through the MySQL driver provided by
Laravel.
From now on, Laravel 11 offers a dedicated MariaDB driver.
Database inspection and improved schema operations
Contributed by Hafez Divandari
According to the documentation:
Laravel 11 provides additional methods for operating and inspecting database schemas, including natively
modifying, renaming and deleting columns. In addition, advanced spatial types, non-default schema names
and native schema methods for manipulating tables, views, columns, indexes and foreign keys are provided:
use Illuminate\Support\Facades\Schema;
$tables = Schema::getTables();
$views = Schema::getViews();
$columns = Schema::getColumns('users');
$indexes = Schema::getIndexes('users');
$foreignKeys = Schema::getForeignKeys('users');
48
Model Casts Improvements
It is now possible with Laravel 11 to use a
casts()
method rather than the
casts
property in your Eloquent
models.
As Luke Downing shows in this video on Laracasts, not only does this improve the readability of your code, it also
means that you won't get any interpretation errors in your IDE.
For example, if you have this code :
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'settings' => AsCollection::class . ':' . SettingsCollection::class,
'achievements' => AsEnumCollection::class . ':' . Achievement::class,
];
and you want to replace it with :
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'settings' => AsCollection::using(SettingsCollection::class),
'achievements' => AsEnumCollection::class . ':' . Achievement::class,
];
your IDE will undoubtedly indicate its dissatisfaction.
With Laravel 11, you can remove your
casts
property and replace it with the
casts()
method as below:
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'settings' => AsCollection::using(SettingsCollection::class),
'achievements' => AsEnumCollection::class . ':' . Achievement::class,
];
}
Note
Examples from Luke Downing's video
Note that there is no obligation if you have a Laravel 10 application to switch your casts in this way, as Laravel 11
supports the old notation.
49
Improved validation for Laravel Prompt
Laravel Prompt is a package developed by Jess Archer that allows you to set up forms in your command-line
applications.
Under Laravel 10, to check the validity of data you had to use rules in this form:
$name = text(
label: 'What is your name?',
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);
With Laravel 11, you can now use Laravel's validators directly. The previous code has therefore been simplified to
become the code below:
$name = text('What is your name?', validate: [
'name' => 'required|min:3|max:255',
]);
This syntax is easier to read and, above all, we're already used to it!
50
Documentation update
Obviously, a new update of Laravel also means an update of the documentation.
The documentation for this new version is as comprehensive as ever.
Don't miss the Prologue
You'll find two really important chapters
Release Notes
and
Upgrade Guide .
The release note gives you a quick overview of everything that's new in the version you're currently reading. It
also gives the minimum PHP version required to run Laravel. For Laravel 11 this is PHP 8.2.
The upgrade guide, which shows you the breaking changes with their impact (high, medium and low) and the
estimated migration time.
Searching the documentation
Don't forget that you can press your '/' key at any time to open the documentation search.
51
Laravel 11: new default home page for your new projects
Just launch a
laravel new l11project .
validate the installer's default proposals, go to the directory
cd l11project
directory
directory and then run
php artisan serve
and go to the suggested local address:
127.0.0.1:8000
and you'll see the new default home page:
This is mainly an aesthetic change.
Here is the old version of the home page under Laravel 10 for comparison:
52
The changes can be summed up as a change of colour, 4 blocks of the same size which become a main block on
the left highlighting the Laravel documentation and three blocks of the same size which still have the same themes:
"Laracasts", "Laravel News" and "Vibrant Ecosystem".
53
Should I migrate from Laravel 10 to Laravel 11?
Sooner or later, it will become necessary, and that means at the end of the life of Laravel 10.
It is important to bear in mind the lifecycle of Laravel versions so that you can correctly anticipate your future
migrations.
To do this, you can consult Laravel's Support Policy.
You then have two options:
start a new application
upgrade an existing application
Start a new application
This is the easiest way.
Just start directly under Laravel 11 with
laravel new . However, don't forget to update the laravel
installer to its
latest version, which supports Laravel 11.
composer global require laravel/installer:^5.6
Upgrading an existing application
We're talking here about migrating a Laravel 10 application so that it supports Laravel 11.
I refer you to the upgrade guide which will give you all the keys to updating your application in the best possible
conditions.
The estimated migration time is about 15 minutes.
54
Next version?
Well, for the moment we're continuing to increment the version number. So it looks like the next version of Laravel
will be Laravel 12, scheduled for release in Q1 2025.
To try out this new version, simply install Laravel in dev mode with the following command:
laravel new l12 --dev
Obviously, as Laravel 11 has just been released at the time of writing, there probably won't be many differences
from the current version.
You can then see the version of Laravel by doing a little :
php artisan about
We don't yet know what's in store for the next version, but we're sure we'll start hearing about it soon. And if you'd
like to find out more about the next version, please check the Laravel Github regularly.
55
Frequently asked questions
I've tried to put together some quick answers to questions you might have.
Where are the files broadcasting.php, cors.php, hashing.php, sanctum.php,
view.php?
These files have been integrated into the core of the Laravel framework and are therefore no longer available in the
config
directory.
What do I do if I want to customise a configuration file?
Simply use the command
php artisan config:publish
and select the file. It will then be copied to the
directory.
What is the minimum PHP version required to run Laravel 11?
PHP 8.2
56
config
Glossary
Middleware
Middleware provides a convenient mechanism for inspecting and filtering incoming HTTP requests to your
application.
Taylor Otwell
Taylor Otwell is the creator of the Laravel PHP framework.
57
Who am I?
Husband and father twice
πͺ
π«‘
Ex-member of the French Navy
I've been passionate about IT since I was 10, and code is in my blood. I'm always up for a
Newsletter creator
laravel new
π
ποΈ :
π«π· Quoi de neuf les devs ?
π«π· Laravel au quotidien
A Day with Laravel
Creator of Framework Heroes
π¦Έπ½βοΈ π¦Έπ»βοΈ
I've been wanting to create this site for several months, to create a job board specialising in devs using frameworks.
I hope you like the concept and that you'll help me develop it by contributing new ideas. It is of course developed
with Laravel.
Discover Framework Heroes
Creator of GiftKeepr
π
If you're tired of receiving gifts that you're going to have to resell, GiftKeepr is for you. Add the gifts you really want
to receive, associate them with an occasion. Share your list with your family, friends, colleagues... and that's it.
Discover GiftKeepr
58
HappyToDev blog
You can also find my latest articles on my blog.
Follow me on the networks
You can find me and follow me on your favourite networks via my links page
59
End
Thank you for reading this carefully. If you have any comments on this ebook, please let me know:
for a typeface
to suggest an improvement
to point out an error
an addition to the FAQ
You can write to me at
See you soon.
Fred
60
happytodev at gmail dot com
or DM me / ping me on your favourite networks.
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )