LARACON EU 2024 // TAYLOR OTWELL :: LARAVEL UPDATE

In this Laracon Europe 2024 presentation, Laravel creator Taylor Otwell delivers a comprehensive update on the Laravel ecosystem. He introduces Laravel 11, emphasizing its slimmer, modern skeleton and a host of developer‑focused improvements such as per‑second rate limiting, the once() helper, eager‑loading of the latest N relations, and new defaults that favor SQLite and database‑backed cache, queue, and session drivers. Configuration publishing has been streamlined, and the framework now auto‑detects four database options (Postgres, SQL Server, MySQL, SQLite). Otwell showcases Laravel Reverb, a WebSocket solution that can scale across multiple servers, and announces its release alongside Laravel 11 in about four weeks, with a dedicated deep‑dive session by author Joe Dixon. He also highlights the Laravel Herd suite—Herd, Herd Pro, and Herd for Windows—as the premier local development experience. The talk wraps with a brief Q&A covering database config visibility and future Linux support, reinforcing Laravel’s commitment to a lean, performant, and developer‑friendly stack.
Chapters
Please welcome the man, the myth, the legend. Make some noise for Taylor Otwell!
Hey everyone, welcome to Laracon Europe.
Thanks for having me. I think this is my 8th or 9th Laracon Europe, maybe almost my 20th Laracon in general. So we've had a lot of these things and they, it feels like they just keep getting better. So thank you for coming. Thank you for supporting this community and this ecosystem. It's great to be back in Amsterdam. And I always love coming here every year. Thanks to all the staff and volunteers that make this event possible, and our sponsors, of course. Be sure to check them out in the lobby and hear what they have to say as well. They've got some great services and products to offer you if you're a Laravel developer, which I assume you are. I've been building Laravel for a while. This makes about 14 years since I wrote the first lines of the Laravel framework in my apartment back in late 2010. And after all of this time, thanks to the great core team we have at Laravel, thanks to all the contributions from the community members like you, I'm still incredibly motivated to keep working on this framework and this ecosystem. Because after all this time, I still feel that this is the singular most productive way to build full-stack web applications. all these years later. Just the development experience, the speed, the productivity of building applications with Laravel is unmatched, I feel like, in the web development ecosystem. And I love making it easy to build web applications. It keeps me energized to keep building this ecosystem. And I have honestly never felt burnt out working on making Laravel awesome for all of you. So thank you. We'll cover a lot of cool new stuff today. Hopefully you find it cool. I think it's cool. And First, I want to get started with just kind of a recap of some interesting things we've done recently, just to sort of bring you up to speed on some things you may have missed. So back at Laracon US, we had the release of Volt and Livewire 3. Volt is an amazing way to build very dynamic, very modern, reactive-feeling applications just in PHP. So— This is a Volt template here where you can see we've defined some interactivity at the top of the template, and then we have, of course, our HTML at the bottom. And there's no build step, there's no JavaScript compilation that has to happen here. We're just editing this code in a Blade template, and we have interactivity right there with no build step. So it's an incredibly productive feedback loop as a developer to be able to just edit the file and hit it in your browser immediately. With no other in-between compilation step. And for many PHP developers, Livewire's been a game changer because it allows you to build these modern reactive applications in the language that you're used to and without the complexity of a lot of other builds and compilation steps and things like that. So I think it's really been a game changer for a lot of people to level up their PHP apps in terms of how they feel to the end user. More polished, more modern, more reactive. We also launched Laravel Herd, which was developed in collaboration with Beyond Code. Herd makes it absolutely incredibly easy to get started building Laravel applications on your Mac. So how it works is you download Herd, which is just an application, a Mac application. You drop it in your Applications folder on your Mac, and you have everything you need to start building Laravel applications. You have PHP. You have Composer, you have the Laravel installer, and you have a bunch of other tools actually within the Herd settings themselves to start building Laravel applications right away. And the cool thing about this to me is it doesn't use any external dependency managers like Homebrew or Docker behind the scenes. Everything is actually compiled into Herd itself so that it's truly one application and the only application you need to get started building Laravel applications. You can literally go to the Apple Store, buy a MacBook, download Herd, and that's all you need to start building Laravel applications, which I think is super cool and is something I have wanted for a long time. This winter we also launched Laravel Pulse. Pulse is the best way to get a high-level overview of your Laravel application's health, and it was developed here at Laravel by Jess Archer and Tim McDonald, 2 of our, of course, incredibly talented developers we have on the team. There's no complicated configuration. You just composer require laravel/pulse, and you're good to go, and you start getting really interesting metrics about your Laravel application immediately. And I tell people I like to think of Pulse as sort of the family doctor. of your Laravel application. It's sort of a good first point of contact to figure out what might be going wrong with your application. So for example, you can see users that are making a lot of requests or an endpoint that is slow or an exception that's been happening a little bit more than usual. And it's a great starting point to maybe dig into some deeper tools from there. Maybe you head over to your preferred error monitoring solution to really dig into a certain exception, or you use a profiling tool to really dig into a certain code path and get down to a really granular level. But Pulse, I think, is the best starting point for figuring out what's actually happening in your Laravel app. And it's something we built based on our own frustrations of wanting to diagnose things in things like Laravel Forge and Vapor really quickly and get answers really quickly when something was happening in production. And we were so frustrated that we weren't able to get these answers as quickly as we would like. And so Laravel Pulse was really the product of that. Scratching our own itch, you might say. We also recently released our FrankenPHP integration with Octane, which you heard about this morning. This integration was contributed by Kevin Douglas, the author of FrankenPHP. It is a super fast, modern PHP application server. Of course, I probably don't have to tell you too much about it since you heard about it this morning, but it keeps your application in memory and serves your requests at a blazing fast rate so that you can really double the speed of your Laravel application just by using a tool like this. And of course, we have first-party Octane integration and FrankenPHP integration in Laravel Forge so that you can deploy these applications very easily to production. Speaking of Forge, we've continued to improve our commercial family of offerings, tools that allow you to get your Laravel application in production as fast and productively as possible. One of the cool new additions we've had recently is the Forge application panel, which was developed by James Brooks here at Laravel. And when you deploy your project, out to Forge, the application panel, which you can see here, automatically detects what Laravel packages you're using and gives you nice toggles to enable them or disable them. So for example, in this project, it knows that I'm using Laravel Octane, and I can flip the toggle switch to turn on or off the Octane server anytime I want. Same with maintenance mode or the Laravel scheduler, Laravel Horizon, or even Inertia's server-side rendering engine. There's a toggle for that as well if you're using that in your application. So it makes it super simple to— or gives a more fuller integrated experience with your Laravel application in Forge and makes it super simple to enable these various services. On Vapor, we recently introduced support for serverless ElastiCache instances on Amazon AWS. So what's cool about this is you can launch a serverless Redis cluster and you do not have to choose how many nodes or what size your cache should be upfront. It will automatically scale to meet the demands of your application. This was integrated into Vapor by Joe Dixon here at Laravel. It's a really cool new feature, and I always love to use these kinds of features because it takes out sort of the decision paralysis of deciding how much resources I actually need for my application. I can just go with a serverless option and let it scale to meet the demand automatically. We also launched support for ARM architecture on Laravel Vapor. ARM processors are more efficient and they're also faster. So it's a win-win and they're also cheaper. So win-win-win on AWS. Um, and to start using an ARM architecture for your Vapor-powered Laravel application, it's truly just as simple as going into your configuration file, going to the runtime line there in the middle and putting -arm at the end of the runtime and then redeploying your application. And within minutes, your whole application is running on an ARM architecture. and you've cut your AWS bill down, and you've increased your performance and efficiency. And this is just a sampling of some of the things we've launched over the last year. And even this screen right here is just another sampling. There's so much more that goes on behind the scenes. And every week, a new release of the Laravel framework is released with a cool new feature and a handful of bug fixes. So I'm incredibly proud of our team and what we've been able to ship. And hopefully you've enjoyed a lot of these things that we've brought to you. over the last year. So that's a brief glimpse into some of the things we've launched recently. What about the future? We have a lot of plans for the future, actually, a lot of exciting new things that we're pumped to develop, and some of them I'll show you today. So let's go ahead and get started. And I'd like to get started with Laravel 11. So let's dive into that.
All right.
Laravel 11, which is scheduled to be released at the beginning of next month. When I first started developing it, I had one primary goal, and that was to simplify the entire development experience. Laravel's been around, like I said, for 13 years publicly, but I've been working on it for 14 years, and over time it's easy to become blind to complexity in software. For example, take the service providers directory of a new Laravel application. It almost becomes assumed that there should be 5 files in that directory in every new Laravel application. You just get used to it. It's sort of insidious the way complexity creeps into software. You add a new file one year, a couple new files the next year, another file the next year, and after a period of years, you've accumulated quite a bit of cruft in your application. And take middleware, for example. It becomes easy to become accustomed to the fact that there should be 9 middleware files in every new Laravel application that every new Laravel developer needs to understand. And it starts to become overwhelming. It feels like we have a few dozen extra files that we don't actually need. So with Laravel 11, I challenged myself to step back and look at the framework with fresh eyes. and say, what do we actually need here? What are the core files that are absolutely required, and what can we strip away to give Laravel a leaner, more minimal, more modern feel? And that was my goal with Laravel 11. And the great thing is, if you're on Laravel 10, when you upgrade to Laravel 11, you don't have to change anything about your application structure. The framework's been fine-tuned internally to support both structures so that the upgrade process is totally seamless. All right, so enough of chattering. Let's get into some actual code. Let's start our exploration with routes. This is usually the first file that people interact with in a Laravel application. And if I open the routes directory, you'll see that it actually has a few less files. It just has a web routes file and a console routes file. And there's no API routes or channel routes by default. And the reason for that is most Laravel applications actually don't have a public-facing API that's consumed by third parties. They just have your own internal routes in your own internal application. So there's no need for us to have this extra API routes file by default. But what if my application does have an API routes file? How can I install it and get back to where I want to be quickly? And we can do that through some new artisan commands. So I'm going to pop open a terminal and I'm going to run php artisan install:api. And this command will add the API routes file. It will install Laravel Sanctum, and I'll be ready to go developing my API with authentication, token-based authentication using Laravel Sanctum, using that one command. Everything is ready to go. It's just that simple. What about channel routes? Let's get rid of our API stuff. Channel routes, if you're not familiar, tie into Laravel's event broadcasting system. So when you're using Laravel's event broadcasting system, you define channels that users will listen to for events for building real-time applications, and you'll broadcast events onto those channels. And again, many applications that are built with Laravel don't use event broadcasting, and this channel routes file can feel unnecessary or like a little bit of file bloat. But how can we get it back if we need it? And we can get it back really easily. So very similarly to the way I installed the API routes, I can just come to my command line and do php artisan install broadcasting, and I'm ready to go. The channels route file is installed, broadcasting route authentication is enabled, and everything is auto-discovered and ready to go to build my application. All right, so it's super simple to get these routes back when you need them, but the default skeleton is slimmer, a little bit leaner for— to fit the use case of most Laravel applications. All right. Let's get rid of that. Close that out. Let's go back to the console/routes file. If we take a look at this file, we can see that we can now schedule commands directly from this file, which was not possible before. So if you look at this closure-based artisan command, you'll see at the very end of it on line 8, I'm chaining on the hourly method. And I could also chain on the daily method or the weekly method or the monthly method. Or whatever schedule I want this command to run, and I can do that right from this file without needing to leave or go anywhere else. What if I have other things I want to schedule? I can use a new schedule facade to say things like schedule even just a closure. I can schedule it to run every second using Laravel's new sub-minute scheduling functionality. I can do that right from this file.
Cool.
And because I can do it from this file, I actually don't need another file, which is the console kernel, which who knows what a console kernel is anyway. But that file's not needed anymore because we can schedule commands and define commands right here from this file and streamline the whole process. Now what if I want to make a class-based Artisan command? I think it's a little bit too complicated for a closure. Maybe I want to put that in a separate file. I can do that really easily using Artisan. So I'll just say artisan make command. Sure, maybe I'll call it send emails, and it's put into my application. Now I can come into that command, put some code in here, sending emails. And now I can run that command without registering anything else in the application. Everything is auto-discovered. There's no need to go into a console or console kernel file and register the command, or if you want to schedule it, there's no need to go in a separate file to do that either. You can do it all from the routes console file. So you can really manage your whole console experience from this singular file. And what that means is your application directory actually becomes much simpler. You just have an HTTP, a models, and a providers directory out of the box. Much leaner. much more streamlined.
Thank you.
So that's what the default routes layout looks like in Laravel. Of course, I'm sure many of you are familiar with the web routes file, which is sort of your standard routes that you would define for your application. Nothing has changed there. So typically these files would be sort of configured and loaded by the route service provider. But in Laravel 11, you'll notice that my app providers directory just has one provider, not 5. This has an AppServiceProvider. So how does the framework know how to find my routes or where they even are on the file system? And that brings me to a really important file in Laravel 11, which is the application bootstrap file. And I like to think of this file as like the route file equivalent of application configuration. It's much more minimal. It's much more functional, whereas a lot of this stuff used to be spread out across about 10 different classes. Things have been consolidated into this file to provide one streamlined app configuration experience so that you can come into this file and get a great overview of the entire configuration of the application without going all over the file system. So how does this file work? Well, first, we call this withProviders method. And what this does is tell the application to load all the service providers for our application. And anytime we want to create our own custom service provider, we can again just use artisan. So let's do artisan make provider. Maybe this is like an invoicing service provider to sort of configure the invoicing section of our application.
Okay.
We'll create that, and what's cool is let me drop some code in here. Maybe I'll just do the classic D&D hello world. And I don't have to go into any other configuration files to register this provider. It's auto-detected by the framework so that if I actually hit this Laravel application, you can see that I hit that hello world statement in that provider. In Laravel 10, you would have had to go into your app configuration file, locate the providers array, and add it manually into that array. In Laravel 11, more things are automatically discovered for you by the framework in a more intelligent way. So it leads to less configuration file changes and more auto-discovery. All right, I'm going to get rid of that provider. Now what about routing? You can see in this file that this is where our application's routes are configured, and this is where the work that used to be done in the route service provider can be easily configured here. And we're leaning hard on Laravel conventions here. So the web routes, of course, get all of the web-based middleware, things like encrypted cookies, sessions, CSRF protection, everything that goes into your traditional web routes in Laravel, while the API routes typically don't receive those things. Maybe they receive a rate-limiting middleware, but they don't receive cookies, for example. So you can see that the API routes are commented out by default, which, you know, makes sense considering new applications don't have an API routes file. But if I bring open my terminal again and run that artisan install:api command that we ran earlier, we'll let that run, and you'll see that Laravel will automatically enable that routes file for me within this file. So when I run that command, it's enabling and disabling these routes on demand based on what my application needs. Whoops, sorry about that. Another new feature of Laravel is the health route, which you'll notice on line 14. And this simple directive defines a route that you can use for uptime monitoring or as a health check for your container orchestration services. And when it's enabled and I hit this URL, what will happen is I'll just get a simple status page that lets me know my application is working. And again, this is just a simple convenience mechanism that you can throw in your favorite uptime monitor, or if you're using something like Kubernetes, to let the system know that your application is healthy and responding. And when this route is hit, Laravel will fire a diagnosing health event that you can listen to and do other health checks that make sense for your application. So for example, if you want to check if your database is up or your cache is up, you can do that when you listen to that event and throw an exception if it's not, which will of course trigger a 500 response from the server, letting your tools know that your application is down. And of course, if you don't want this route at all, you can just delete it from your configuration and build your own health route as you see fit. Now, what if we want to customize how routing is done in a more bespoke way, a way that we might have done typically in the route service provider, some really heavy customization of how routes are initialized? We can do that by registering a then callback. And within this closure, we can do anything we want. We can make route groups. Anything we need to do within this closure, we can do to define our routes however we want to do. So this lets you hook into the entire routing system and customize anything you need for the needs of your application. All right. What about middleware? We can see this with middleware method. First, let's look in the HTTP directory of this application. And you can see that there's actually no middleware directory at all in Laravel 11. And it's not there until you actually need it to be there when you create a middleware. So the skeleton used to contain 9 middleware, like I said, and I feel like that's just kind of a lot of files to put in a default Laravel application. It feels kind of heavy, it feels kind of bloated. And the only reason many of these files were there is because they had one property on them that could be customized to, for example, disable CSRF protection on one URI or say that one piece of input should not have the whitespace trimmed around the input value. And a lot of these values were never customized by any Laravel application. They were just standard default values that made sense for most applications, and there was no need to ever tweak them. But what if we do? How would we tweak them in Laravel 11? And it's super simple. Using this method, I can do lots of different things with the middleware stack in the application. So, for example, I can say middleware validate CSRF tokens except these URIs, and maybe I put, you know, no CSRF URI here, and CSRF protection will be disabled for that URI. Same with trimming strings. So I can just do trim strings except, and then I can list the strings that should not have the whitespace trimmed around their input value. So it's really easy to customize that behavior. But what if we want to add new middleware to the application? How would we do that? Let's go ahead and create one. Again, we'll use artisan. php artisan make:middleware. Maybe we could call it ensureSubscribed to make sure our user is subscribed to our application. That will put it in the HTTP middleware directory, and I like that only the middleware that actually belong to my application are in this directory. It's not muddled in with other core framework middleware. I can see my own application sort of shining through the file system without getting distracted by a bunch of core Laravel frameworky things. I can just focus on what matters for my app. Now, of course, I've got this middleware here. Maybe we put some code here in middleware. And maybe we want to add it to the entire web stack, so we want to append it to the web stack of middleware so that all web routes receive this middleware. What we can actually do is just say middleware web.append ensure_subscribed, import that class, and that should put it on all of the routes in the web stack. Just that easily. Of course, we could also add this middleware in the routes file by just attaching it to a route directly, but if we wanted to do it to the whole stack, we could do it from right here. We could also do things like prepend the middleware to the middleware stack, or we could do a variety of operations to the middleware stack. We could prepend things, maybe appending other things, and we can even replace. some core Laravel middleware, like maybe we want to replace the authenticate middleware with our own custom authenticate middleware. We can do that right here from this file. And what this lets us do is when we come into a new Laravel application, we can look at this file to get a quick overview of what's customized about the application, how its middleware is set up, how its exception handling is set up, how its routes are configured, and one file to get a good overview really quickly for how the application is configured in a very streamlined way without jumping around to 10 different files.
All right.
Let's see. What else is in this file? The withExceptions method. The withExceptions method lets us customize, as you might guess, the exception handling properties of the application. So, for example, I could say that certain exceptions should not be reported to our exception logging system at all. You know, so we should ignore some custom exception that we have in our application. We don't want that to go to Sentry, for example, for reporting. We also define how certain exceptions are rendered. So we could say exceptions renderable, some custom exception, and we could return some view here for how this exception should be rendered. All right, so we can customize how the exceptions are rendered and how they're logged. We could even send them to some third-party monitoring service right from this method. Now, some of you might be thinking, what if I don't want to put all of that stuff in this file? And what I like about this actually more minimal structure is it gives you more freedom to build the application structure that you want. So let's, for example, go back to the middleware method, the with middleware method. And what if we want to encapsulate all of our middleware configuration into a different file to maybe house that separately from the rest of the application bootstrapping because maybe it's a little bit complicated in our case? We could actually just make a new class using Laravel 11's new make class command. We'll make that an invocable class. We could call it something like, oh, let's say actions/configure middleware. That will drop it in the app/actions/configure middleware file. And then we could always just new up that file right here and pass it the middleware and let that take care of configuring all the middleware for our application. And we could house it all within this invocable action. So with the new minimal application skeleton, you can feel like you have some freedom to sort of build the bootstrapping process that makes sense for you. And however much scaffolding that you want around your bootstrapping process and how your application is started, you get to choose how heavy that is or how light that is. But by default, it is slim, modern, and streamlined into this singular file where we can see everything that's going on. So feel free to enjoy that flexibility as you start building your own Laravel applications. All right. So let's come back to providers for a second. I said that there's only one provider in every new Laravel application, and that's the AppServiceProvider. Now what about the other providers? Where have they gone? So for example, the BroadcastServiceProvider used to be in every default Laravel 10 application. It's no longer needed because the broadcast routes are automatically discovered by the framework when you enable them. And the broadcast authentication routes that are used to authenticate a user's access to a channel are also automatically registered when the framework knows that you've enabled broadcasting. There's no need for the broadcast service provider at all because it doesn't have any purpose anymore. The auth service provider, again, is not needed because authorization policies are also auto-discovered. So if we have an authorization policy and we have a corresponding model, the framework knows that the policy goes with the model, and there's no need to go into a service provider and register it by hand. So the entire development feedback loop is much quicker and much more based on auto-discovery. What about the event service provider? You know, this is where we used to list our events and our listeners for our application. That's also not needed because event discovery is enabled by default. and Laravel 11. And let me show you what that looks like. So if I go into Artisan and make a new event, maybe podcast processed as it suggests, and then we'll also make a listener for that event. We'll call this send podcast notification or something. And I love how Laravel prompts give me— gives me this dropdown here of my available events. In this case, I just have one and I can just select the event that this listener handles, and it will automatically put that event in the listener file. So if I jump into that listener, I'll put some code here. Podcast processed. And now from my route, I can just dispatch that event. All right. And I don't have to go into any service provider or configuration file to tell Laravel where the listener is. I should just be able to hit this route and see that the podcast was processed. And Laravel does this by reading the type hint information on our listener. So it can see that this listener requests the podcast processed event. So it knows where the event needs to be routed to and what listener it needs to go to. There's no need for an event service provider to configure those things. Of course, if you do happen to have some complicated configuration or event registration logic that's bespoke and complicated for your application, you can always just put it in the app service provider. There was nothing magical about having 5 service providers. It was just sort of bloat that had accumulated over the years, but you could always just use the app service provider for anything you need. All right, that's kind of enough about the app bootstrapping process. Let's talk about a few other things in Laravel 11. So let's hop into the database migrations folder, and you can see that the migrations have been squashed a little bit. So there's users, the cache, and jobs as the 3 default migrations. And as you might expect, they create the users table as well as a sessions database table. a cache table and a cache locks table, and our jobs database table. And that's because in Laravel 11, the database driver is the default driver for cache, queues, and sessions. And this is in keeping with Laravel 11's push for simplicity. The database driver is a great place to start, not only for local development, but it's robust enough to actually ship into production. and get your application actually pretty far in terms of scalability before you have to move to a different option. I also really like the database driver for local development because it's very easy to inspect what's in the cache or what's in the queue or what's in the sessions table just by using your database tool that you're already using to look at the rest of your data. So you don't need to install any other services like Redis to dig into your queue. It's a little bit harder to inspect. You can just look at the database. And continuing on the topic of databases, for new applications, when you use the Laravel installer, the default database system that it will ask you to use will be SQLite. And this is only a decision you have to make when you create a new Laravel application, because what's cool is no matter what database you choose here, Laravel will automatically configure your environment file for the database that you pick. But by default, this option will be selecting SQLite, which gives us a nice, self-contained, fast, minimal database across all operating systems without needing to install any additional software. So it's a great starting point. And you might have also noticed when I created this new app, that it also selected Pest as the default testing framework. Again, this is something that you only have to choose when you create a new app. And what's great is in Laravel 11, Laravel will actually automatically detect which testing framework you're using. And when I run the make test command, it will automatically create the properly formatted test for my testing framework. So I choose PHPUnit or Pest up front. And then from then on, I can just use artisan make test. test, invoice test, for example. And in this example, it will be created using Pest syntax. But if I had chosen PHPUnit, it would have created a PHPUnit test without me needing to pass any additional arguments to the make test command. It just knows what my application needs. So, All right, so the last topic I want to cover on the Laravel 11 application structure is configuration. And by default, you'll see there is no configuration. So we approach this in a couple of different ways. We've greatly expanded the use of environment variables, and we've added more environment variables to the example environment file. So you can now configure things like your fallback application locale. Your application maintenance mode driver, and other things directly from this file. And that means when you're starting your application, you really only have to configure it in one singular file and not across 10 different configuration files. You can get one overall picture of how your application is configured here. But what if your application grows and you need those configuration files back? Maybe you're going to have multiple database connections in your application, and you actually need the database configuration file in your application in order to configure that. Again, let's just use Artisan. We can use the new config publish command, which works great with Laravel prompts, and it gives me a nice user-friendly scrollable list of all the available configuration files that I can publish. So let's pick the database file. That will put it right here in my config directory. And what's really great about Laravel 11 is any of the options I don't need in this file, I can actually just remove them entirely, and the framework's defaults will be used instead. So I only need the configuration options that I'm actually customizing for my application to stay in this file, which means I can make the files much leaner and more streamlined for my actual customization needs.
Yeah. Thanks.
Now, what if I just want all the configuration files back? Maybe I like having all those configuration files. I can just run artisan config publish --all, and every configuration file will be published to the configuration directory for me to browse through and see what options are available. And I can always remove the files I don't need later once I've kind of figured out how my application's going to be configured. All right. So I think that's pretty much everything I wanted to cover in terms of the application structure. of Laravel 11. Hopefully you find it slimmer, leaner, more modern, and I hope less overwhelming for new developers into the Laravel ecosystem to not have to learn what 20 different files do in a new Laravel application. It's a more streamlined, leaner, modern experience, I think, that sets us up for a good— the next 10 years of Laravel development, let's say. All right, so Laravel 11 is not just about application structure. There are actually new features in this version of Laravel. And I'd like to dive into some of those now. All right, so let's clear out everything we've done here, and I'm going to switch to another branch, Laracon EU demo. All right, so I'm going to walk through some of the cool new highlights in Laravel 11 and show you some of the new things that it can do. And I'm going to start with the once function, an all-time favorite of mine that is near and dear to my heart. I wrote this function back in November of 2016 and put it in a GitHub gist, just publicly like, hey, here's a cool idea that might be neat in Laravel. It was eventually turned into a Spatie package, as all code must be, through a rite of passage before it goes anywhere else. And now we've eventually incorporated that idea back into the framework because I feel like it is so, so helpful. And let me show you how it works. So in this route, I'm newing up an InvoiceService, and then I'm calling this all method twice. You can see right there on lines 21 and 22, and then I'm going to new up the service again to get a new instance and call the all method again on line 27. And let me show you what this method looks like. So if I hop into the InvoiceService, you can see that the all method calls this once function, which accepts a function, and the return value of this closure will be locally cached by the once function for this instance. of the service, and any time that I call this again, I'll get the same result back out. So you can see here we're returning an array of 3 random strings. So what we would expect to happen in this route is we would expect these first 2 calls to return the exact same array, and we would expect this 3rd call to actually return an array of different strings because this is a new instance of the service. So let's actually hit this route and see what happens. All right, and you can see here, here's those first 2 dumps we made, and you can see they are in fact the same strings in the array. And you can see on this 3rd dump that they're different strings because it was a new instance of the service. So this once function, it's just a really convenient helper for memoizing the results of a function, and I find myself using this a lot in form requests and queued jobs when I need to maybe retrieve something from the database. or do something computationally expensive, the once function sort of saves you from having to make a local variable, store the results in the variable, store that on the instance, return it, check if it's been set. That whole song and dance is eliminated by the once function, which I find super helpful, and hopefully you do too. Tim McDonald has contributed a great new feature to Laravel 11, and it's per-second rate limiting. So in Laravel 10, of course, you can throttle requests to a certain endpoint using either the cache or Redis or some sort of atomic locking system. But in Laravel 10, you could only do that at the minute level of granularity. So you could say that I expect this endpoint, or I don't want to allow this endpoint to get any more than 5 requests per minute. And how you would do that is, let me hop into my App Service Provider is you would define a rate limiter and you would just give it an arbitrary name of your choosing, and you could just say that, you know, I want to limit this per minute to 5 requests. Well, similarly, now in Laravel 11, you can say limit per second. So there are some applications out there that actually need per-second granularity on rate limiting, and if that is you, you're in luck in Laravel 11 because you can now do that. So If we hop back into these routes, you can see that on this first route, on line 36, I'm assigning that the per-minute rate limiter. That's the minute route. And down here on line 38, on the second route, I'm assigning that the laragon-second rate limiter, which is at second-level granularity for rate limiting. So let's actually try hitting these routes. So I'll go to the minute route in my web browser, and we should be able to hit this a few times before we eventually hit the rate limit, of course, because we limited it to, I think, 5 requests per minute. Now, if we hit the second route, we should be able to keep hitting this pretty much indefinitely as long as we don't make one or more than one request per second. But if I start trying to hit it really fast, you can see that I'm, of course, getting rate limited down to the per-second level. So this is a great new feature in Laravel 11 for those of you that have potentially very high traffic applications that need per-second rate limiting on your API or even on your app itself. So thank you, Tim, for that feature. This next feature is a very highly requested feature for a number of years. And let me give you an illustration of what it does. So first, let's look at our database seeder. And you can see that we have 2 test users here. And I'm going to assign each user 10 blog posts. So just imagine a simple system where we have users, users can have blog posts, and users can have any number of blog posts potentially, but these users have 10 apiece. And let's imagine we want to load the users from the database and we want to eager load their posts in the same Eloquent operation, but we want to get the latest post and only the 3 latest posts for each user. So in this case, we want to get back the 2 users and 3 posts per user that are sorted by the date they were posted. In Laravel 10, this was just not possible at all without requiring an external package, actually. But in Laravel 11, we've integrated the open source work done by Jonas Staudemeyer in this regard, and now it's just built right into the framework. So let's go ahead and hit this route. And you can see we get the user, we get 3 posts, we get the second user, and we get their 3 latest posts as well. So it's super simple. This is a very common use case actually, and I'm super pumped that we were able to get this in Laravel 11. And hopefully that makes your life quite a bit easier when you encounter this situation. Now I'm actually going to stay on the topic of databases for a second. Did you know that Laravel actually has these cool commands built in like model show user? And it will actually dump out information about your Eloquent model. For example, all of its attributes, what data type they are in the database, what relationships the model has, any event observers that are registered with the model. There's also the artisan db table command. Command which dumps out information about a specific database table. It's just a quick way to sort of inspect your database table at a moment's notice and sort of remind yourself of what the structure is or what the data types are in the table. And if you've ever run these commands on Laravel 10, you might notice that it's a little bit different on Laravel 11. On Laravel 10, when you run these commands, you're prompted to install another library before you can continue, and that's the Doctrine database abstraction library. And in Laravel 11, we're no longer dependent on this library. So it slims down your dependencies quite a bit because that's a big dependency to include in your application. And now you can inspect your database and even update and change the data types of columns without installing any additional packages because all of that work is now handled natively in Laravel itself. So we've eliminated that dependency from the framework. Now I want to talk a little bit about queue testing. So I recently contributed a feature myself to Laravel to make a certain queue testing scenario much easier. Where's my queue test? There it is.
All right.
So let's imagine we have this process podcast queue job. And if we go into this job, if the ID is 123, we'll release the job back onto the queue with a 30-second delay. So we'll say, hey, Hey, we're not ready to process this job yet. Try it again in 30 seconds. And in Laravel 10, there was no way to actually test that this happened in a feature test, to test that the job was released back out onto the queue with a certain delay, or to test that the job was deleted manually, or that it failed manually by the developer. So I recently contributed a feature to Laravel 11 to make this super easy. So what you can do is actually in your test, you can say that you want this job to have fake queue interactions. So this stubs out the interacts_with_queue trait that is available on this job, and it allows us to test the interactions with those methods. So now that I've faked those interactions, I can just come down here and say job.assert_released and run that test, and we can see that the test passes. And of course, I can actually pass the delay that I expected there to be. And if the delay is not what we expect it to be, you can see that the test fails. And it says that we expected the job to be released with a delay of 45 seconds, but it was actually released with a delay of 30 seconds. So we can correct that behavior. So it makes it much easier to test this, whereas before you would have actually had to extend the job, build a fake release method all on your own, keep track of if it's been called or not. It was a real hassle. So this makes it much more streamlined, much more efficient to test these applications. validations which weren't testable before. All right. Let's talk about command line validation and Laravel Prompts specifically. So I'm going to hop into my routes console file. And as you know, last year we released Laravel Prompts, which was developed by Jess Archer here at Laravel. a groundbreaking new CLI library, I would say, for PHP and something that really hadn't been done before in the PHP ecosystem to be able to have these very interactive, beautiful prompts on your command line when you interact with your Laravel application. So what if you want to use Laravel Prompts and validate the data that a user is typing into your command line application? This is how the Laravel Prompts documentation shows it currently. So you pass a closure to the validate argument. That closure receives the value of this— whatever the user types in on the command line, and then you sort of have arbitrary control over what you do from there. So, for example, in this situation, I'm saying if the string length is less than 3, we want to show an error message that the name must be less— or at least 3 characters. If it's greater than 6, we'll say that the name must not be longer than 6 characters. And you can see if we hit this command on the command line and say, for example, I do, you know, something really short, it will say the name must be at least 3 characters. If I do, for example, 6 characters, that actually passes the validation. But if I do something a little bit longer, that actually fails the validation. So we can see that that's working. But you can imagine as your rules got a little bit more complex, if you needed to do more validation, this would become a little bit of a mouthful to put all of this code in here, and it would be a little bit cumbersome. Well, the good news is Laravel actually has a really awesome validator built in. So what if we could just leverage that to validate our prompts, which is exactly what we can do in Laravel 11. So we can actually just delete all of this code, say name. Let's actually just shorten this to required, min 3. Max 6, just like we would validate an HTTP request. And now let's try this command again. You can see that it's working as we expect. If the name is too short, it tells us it needs to be longer. If it's just right, it lets us pass the validation.
So—
You can actually tap into the full power of the Laravel validator from your Laravel prompts in Laravel 11, which I think is a super cool new feature.
All right.
Moving on. Let's talk about encryption. I want to show you a new feature that I actually recently contributed to assist with encryption key rotation. Encryption is used on every new request to Laravel because every cookie that's added to the response by the framework is actually encrypted and signed with an authentication code. So you can't avoid using encryption if you're using Laravel. Of course, we're a very security-minded framework, and it's sort of baked into a lot of the core functionality of what we do in terms of session handling and cookie handling. Now, let me go ahead and, like, register a new user with this application. All right, so let's go in here. I'm going to hit register. I've already sort of preceded this form. All right, we have a new account. Now let's say we want to rotate our encryption key. So the encryption key is the app_key in our environment file. So most of you are probably familiar with this key. That is what is used to actually encrypt the data. That's the key that is used to perform that encryption. Now what you'll notice is that if I rotate this key, key generate, forced to generate a new key. And then if we try to hit this application, we're actually logged out. And that's because when the next request came in, Laravel was unable to decrypt that cookie because we changed the encryption key. So it discarded the cookie as invalid, which logged us out of the application. And of course, that's not very fun for our users. We don't want them to be logged out of the application if we need to rotate the encryption key. This also presents a problem if we have encrypted data stored in the database. So for example, let me reseed the database. And you can see in this example, I'm pulling a user from the database. And if I look at that user model, the passphrase has the encrypted cast on it. So that means that when we store this value in the database, we want Laravel to encrypt it for us when it stores it in the database column. And if we look at our database, Wrong database. If we look at our database and we see that passphrase column right here, you can see that it is encrypted. It's a big, long, jumbled string of data. All right. So on this encryption route, we're just going to pull the user. We're going to pull the passphrase. We're going to pretend we do some work maybe during the request. We put the passphrase back on the user. We save it back to the database, and then we return the original passphrase. So let's see if we can actually decrypt this, which we should be able to. Hit the encryption route. Okay, my secret phrase, which is what was encrypted into that column. Now again, what if we rotated our encryption key? Let's go ahead and do that. And we can see if we hit the route again, we get an error that we were unable to decrypt that data. So all the encrypted data stored in our database is now invalid. Okay, yikes. That's not good. What we really want to do is be able to rotate these encryption keys gracefully. All right? And I contributed a feature to Laravel 11 to do just that. So let me show you how it works. Let's hop back into our app, get a fresh database on our hands here. And let's go ahead and go into the application, register. All right. We're back in. Let's walk through that original scenario again and see how we could handle it differently with encryption key rotation. So I'm going to go back into my application, and I'm actually going to duplicate this key to a new previous_keys environment variable. All right? So I'm going to put the old key there. Then I'm going to rotate the encryption key just like we did before. All right? So now if I hit the application, you can see I'm not being logged out. So how does this work? And how it works is when Laravel encrypts data, it will always use the master application key, the app_key. But when we decrypt data, we'll try the current key first, but if it doesn't work, we'll try the previous keys that have been configured. One of those works, and then we'll re-encrypt the data using the new key so that everything is gracefully migrated to the new encryption key over time as users hit the application. All right? It's the same way, or it's a similar situation with the application that's stored in the database.
Okay.
So let's reseed the database. We have that user passphrase. Okay. My secret phrase. Let's try to rotate the key again and see if we can still get this phrase. All right. So again, we'll copy this. App previous keys. We will rotate the encryption key. And we should be able to still hit this route with no errors. And the data was actually saved back to the database using the new encryption key So now it's been updated to our rotated key gracefully and automatically with no errors for our users. All right. Next, I want to finish up with one quick feature, uh, also related to security, which is automatically upgrading the bcrypt work factor. of your stored passwords. I'm sorry we're getting a little bit into the weeds here in terms of security, but I think this feature will be very valuable to your apps. All right. Fresh database again. Now, if we look into this database and we look at our users table on the password column, this is a little small. I'm not sure if you can see this, but right here there's a $12. And what that actually means is this is a bcrypt hash. bcrypt is a hash for hashing passwords. It's a slow, hashing algorithm, which is great for hashing passwords. You actually don't want your password hashing algorithm to be fast because it's easier to brute force your passwords if it's very quick to calculate the hashes. So bcrypt is cool because it actually lets you configure how slow it is, and that $12 is sort of the work factor, it's called, of the bcrypt hashing algorithm. And you can increase or decrease that based on the computational power over time. So as the years go by GPUs get faster, CPUs get faster. You typically want to increase the work factor to match the increasing processor capabilities, you know, here in the real world so that your applications can't be brute forced. So in Laravel 11, this can actually be done for you automatically. So I'm going to actually register my new user again. All right. I'm in the system. There's my new user record with the 12 work factor. Now, if I go into my environment file, there's actually a new option of bcrypt rounds, and let's bump that up to 13. Maybe we think processors are getting a lot faster, we want to increase our work factor. Now, what happens is the next time the user logs into the application, the password will be automatically rehashed to use the new work factor. seamlessly without anything needing to be done on you, the developer's part. Your passwords are kept up to date on the latest work factor configured for your application as users log in. It's all totally seamless. All right. So that is a preview of Laravel 11, which again we plan to release in early March, probably the first week of March. I hope you really enjoy the minimal new structure. It has a more modern, lean feel and lets you build the application you want while letting your application shine through without a lot of file system bloat. So that's it.
Thank you, Taylor.
I didn't.
Is he set now? Apparently.
No, I need to get this— we need to get this working. Oh my.
Yeah, that's old. That happened strangely at the same time.
Ba ba ba. How are you doing?
Good, but there's still more to show. You're going to stand there? Okay. Okay. At Laravel— or at Laracon US, we introduced Laravel Herd, a new desktop application for Mac that includes everything you need to get started building Laravel applications. And like I said, it doesn't provide any of this through external dependency managers or Docker or Homebrew or anything like that. It's all self-contained. And Herd Herd is an amazing contribution to the Laravel ecosystem in collaboration with Beyond Code. But we thought there could be even more that Herd could do for your applications. So now I'm pleased to introduce you to Herd Pro. And I'd like to show you some of the cool new features that are available in this new edition of Laravel Herd. All right. So the first new feature I want to show you is mail debugging. I've actually got Herd Pro running on my laptop already. And you can see in this route, I'm just sending an email to the application. And let's see what happens when I do that. We can see we have a new mail debugger built right into Laravel Herd. So as I send emails, you can see them coming into this inbox. I can actually inspect the emails. what they look like, all of their headers directly from Laravel Herd without needing any external tools. And it's a really great way to preview these emails without needing to send them to a real inbox. And you can see here when I don't have any mail, I have a nice empty state here that shows me how to configure my application to send emails to Laravel Herd. All right. So the next thing I wanna show you is related to dumps. So dump is a popular function in Laravel, and in Herd Pro, it can actually intercept your dumps for you and show them to you right there from Herd. So let's go to this route. If I hit dumps, you can see, of course, we get this dump at the top of the screen, as you might expect. Now in Herd Pro, I can actually bring up a dump Whoops, not the mail. I can actually bring up a dump server. All right, let's clear that out. And I can just hit this antenna button to start listening for dumps from my application. So I can kind of toggle that on and off as I need it. And when I dump something, it shows up right here in the dump server integrated directly into Herd. And I can even pin this window on the top of everything else. So it's super easy to start debugging these dumps and get them out of your application. And of course, I can just turn that off when I'm not interested anymore.
All right.
Herd Pro also has a built-in log viewer. So I can open up the logs tab and I can see all the recent logs for this application. And I can even search through my logs in a really easy-to-use intuitive interface baked right into Laravel Herd. No additional software needed. All right. So that's Laravel HerdPro's log viewer. Now the next feature is something that I think is pretty powerful and that I think a lot of you might enjoy. HerdPro makes it super easy to interact with Xdebug and set breakpoints in your code with zero configuration on your part. So let me actually open up PhpStorm.
Woo!
All right. So here we go. This is the same application we've been looking at. If I come into this route, maybe we set like a variable here that is a random string.
All right.
I'm going to kind of do halvesies here. All right. I'll put my browser on this half. All right. And then let's come in here and let's set a breakpoint here.
Okay.
So we want to maybe intercept the Laravel application's execution at this point, and we'll hit this root route of our application, and you'll see that we're prompted if we want to allow this incoming connection from Xdebug. We will accept that, and boom, we've hit this breakpoint. We can actually see, of course, the contents of this variable as we're stopped right here on this breakpoint. You can see my browser is still spinning. I can step into this code and sort of debug what is happening in my Laravel application with, again, zero configuration on your part. It's just baked right into HerdPro and it works like magic. All right, let's hit this and we can just go through the entire application and you can see now we got the response. All right, and again, we can come back to our web routes file, remove the breakpoint, Hit the application, and we're not stopped at all because the breakpoint's been removed. All right. So automatic integration with Xdebug, powerful integration with PhpStorm, all streamlined and automatic.
Awesome.
So that's a quick preview of Herd Pro, the best way to develop Laravel applications on a Mac. But what if you're not on a Mac? I love Mac, you know, as much as anyone. Y'all know that. But the reality is a lot of our developers are actually on Windows. And for a lot of developers around the world, buying a Mac is actually not economically accessible. They're on Windows machines. Actually, the majority of the users that hit the Laravel website are on a Windows machine. We've heard from developers for years that they want Valet for Windows. What about Windows? You're forgetting about Windows. Don't just focus on Mac. And we've heard you. So I just happen to have— As one does, an extra Windows PC right here in my backpack.
You have it? Thank you.
Hair is golden.
Yeah.
Alright, so let me let this boot up.
Alright, so we're gonna All right.
Here we go. Am I on Windows yet?
All right.
Welcome to Windows.
All right.
We can see here if I go to my taskbar, and I'm pleased to show you for the first time, Heard for Windows. All right. All of the same features you're used to in the Mac version, even the Herd Pro features that I showed you earlier, are in this new Herd for Windows. And just like the Mac version, everything is bundled into Herd. There's no need for Docker. There's no need for any external package manager. You buy a new Windows laptop, you install Laravel Herd, and you're ready to start developing Laravel applications. And you can see here, if I open up my Edge browser, that laravel.test pulls up the Laravel application just like Herd or Valet would. It's an incredibly productive development experience, and I think will be an awesome contribution to the Windows PHP community. And I'm happy to announce that Herd for Windows will be coming out next month with Laravel 11, but that Herd Pro is available today. So, you can go to the Heard website and check that out immediately and start enjoying that. All right, I'm going to switch back to my Mac. That's not a Windows disk, but I just, you know, the rest of the presentation's on the Mac.
All right.
I've got one more thing. I'm sorry, I know it's been a long talk. Let's wrap up here, finish strong. So before I wrap up, the last thing I want to show you, and to preface this, about 8 years ago we launched a library called Laravel Echo, and Laravel received the event broadcasting feature in the framework. And event broadcasting lets you broadcast your PHP events to the frontend to build real-time applications. And we use this extensively on things like Laravel Forge and Laravel Vapor to give real-time updates as your deployment is happening. Of course, you get the output of the deployment as it's happening, or you get the status of your server provisioning as it's actually happening. That's powered by event broadcasting and Laravel Echo. Now, Laravel's event broadcasting capabilities work with a couple of different backends. So right now on the Laravel documentation, we have official integration with Pusher and Ably, which are both commercial serverless applications for using WebSockets. Great solutions, but it's always bothered me that we didn't have our own Laravel-maintained first-party open-source WebSocket server. So today I'm happy to introduce you to Laravel Reverb. So if you go to the Reverb website, you can start sending me some emojis here. This is all powered by Reverb. You can send those in real time to each other. Laravel Reverb is an extremely powerful and blazing fast WebSocket server for PHP. Of course, it's Pusher protocol compatible, so it works immediately with Laravel Echo, and it's built for scale. It's the first PHP WebSocket server to be horizontally scalable using Redis Pub/Sub, so you can scale—
thank you.
So you can scale your WebSocket solution across multiple servers to handle tons of connections for your app. This is actually running on a very small singular web server, and you can see that we're not struggling at all to handle all of these emojis. So Laravel Reverb will be coming next month with Laravel 11, about 4 weeks away. I'm not going to dig into the details of Laravel Reverb, but you don't have to wait long because in the morning Joe Dixon the author of Reverb, is going to give you the full tour of Laravel Reverb and everything that comes with it, which I hope that you'll definitely enjoy. So Laravel 11, slim, modern, lean, new skeleton for the future. Herd, Herd Pro, and Herd for Windows, the best PHP development experience anywhere. And Reverb coming soon next month. I hope you enjoy all of these new things. Let's go have a drink and hang out.
Thank you. Thank you, Taylor.
I have questions. Let me just go there.
Actually, a lot.
I'm going to cherry-pick some.
Okay.
Because people are craving for a beer. So first of all, Gus.
Yep.
Pretty sure that you know that guy. He's asking, why does the config instance install not know about the database that I'm using? So it only shows SQLite and MySQL options?
We show Postgres and SQL Server, SQLite, MySQL, so there's 4 options out of the box, and they'll configure automatically based on what you choose.
It's working. Bum bum bum. That's great. So, last one. Eurodev is asking, what about Linux?
Next year.
Next year. Next year.
More from Taylor

Everything New with Laravel and Cloud | Taylor Otwell Keynote at Laracon US 2026

In conversation with Taylor Otwell: The India Comeback - Hosted by Vishal Rajpurohit

Introducing Laravel VPS & Major Updates to Forge | Laracon Keynote 2025 (Taylor Otwell & Team)

Introducing Nightwatch for Laravel | Taylor Otwell & Jess Archer Keynote at LaraconAU 2024

Laravel Cloud, Inertia 2.0, VS Code Extension, & OSS Updates | Taylor Otwell Keynote | Laracon US

Taylor Otwell "Laravel Herd, Laravel 11, Laravel Folio, Laravel Volt" - Laracon US 2023 Nashville



