Introduction
By enabling middleware based on environment, developers can ensure that their application behaves differently depending on the environment it is running in. For example, developers can use this feature to enable debugging middleware in the development environment and disable it in the production environment. Alternatively maybe you have some error tracking software like Sentry, or custom logging to GCP that you only want running in production environments.
Usng the 'App::environment' method that Laravel provides, we can check the environment that your application is in.
Setting Up Some Example Middleware
To demonstrate how to enable middleware based on environment in Laravel, let's set up some example middleware.
First, create a new middleware using the following command:
php artisan make:middleware ExampleMiddleware
This will create a new file called ExampleMiddleware.php
in the app/Http/Middleware
directory.
Next, open the ExampleMiddleware.php
file and add the following code:
namespace App\Http\Middleware;
use Closure;
class ExampleMiddleware
{
public function handle($request, Closure $next)
{
Log::debug('ExampleMiddleware: Triggered');
return $next($request);
}
}
This is a basic middleware example that simply passes the request through to the next middleware in the pipeline. You can add your own custom logic to this middleware as needed. In our case, we'll add a simple log so we can see when it gets triggered.
Finally, register the middleware in the app/Http/Kernel.php
file. Add the following code to the $routeMiddleware
array:
'example' => \App\Http\Middleware\ExampleMiddleware::class,
Now you can use the example
middleware in your routes or controller methods as needed.
Enabling Middleware Based on Environment
Basic Conditional Statements
Now, let's modify the ExampleMiddleware
class to only run in the production
environment. To do this, add the following code to the handle
method:
if (! app()->environment('production')) {
return;
}
This will ensure that the middleware only runs in the production
environment.
This is arguably the simplest method of ensuring the logic in your middleware only runs in a specific environment. But there are a couple of other strategies.
Conditional Registration of Middleware
If you prefer, you can add conditional arguments directly to the middleware stack in App\Http\Kernel.php
. This is probably the next simplest solution, and has the added benefit of keeping all of your environment configuration details in the Kernel.
protected $middleware = [
// ... Other middleware
app()->environment('production')
? \App\Http\Middleware\ExampleMiddleware::class
: ''
];
In the above example we very simply append on the class in the correct environment. But what if we want to append more than one set of middleware to the stack? We can do that too:
protected $middleware = [
// ... Other middleware
...app()->environment('production') ? [
\App\Http\Middleware\ExampleMiddleware::class,
\App\Http\Middleware\ExampleMiddlewareTwo::class,
] : []
];
The above example merges the $middleware
array and the example classes when the environment is set to production.
Creating Environment Groups
Another neat solution is to create a middleware property in the App\Http\Kernel
class and add your example middleware to that group. Then, add a conditional statement to check if the application is running in the production environment using the App::environment()
method.
If the application is running in the production environment, the middleware group can be added to the global middleware stack.
// App\Http\Kernel.php
public function __construct(Application $app, Router $router)
{
parent::__construct($app, $router);
if (app()->environment('production')) {
$this->middleware = array_merge(
$this->middleware,
$this->productionMiddleware
);
}
}
protected $productionMiddleware = [
\App\Http\Middleware\ForceHttps::class,
];
In the above example, the ExampleMiddleware
is only added to a new production
middleware property. Then, in the constructor of the App\Http\Kernel
class, a conditional statement is used to add the production
middleware global middleware stack, if the application is running in the production environment.
You could extend this for other environments too, if you had a stack of middleware for each:
public function __construct(Application $app, Router $router)
{
parent::__construct($app, $router);
$this->middleware = array_merge(
$this->middleware,
$this->{app()->environment().'Middleware'}
);
}
protected $productionMiddleware = [
\App\Http\Middleware\ProductionMiddleware::class,
];
protected $testingMiddleware = [
\App\Http\Middleware\TestingMiddleware::class,
];
protected $developmentMiddleware = [
//
];
Laravel will automatically detect the environment you're in, and add that middleware stack to the global stack of middleware in your application.
Conclusion
As you can see, there are a bunch of different ways you can handle this kind of logic in a Laravel app. These are just a few that I've personally employed in my experience. What you choose to use will come down to what you find easiest to work with, and what suits the complexity of you app best.
Simple apps might just need a few conditions here or there. More complex apps might warrant adding some of the more dynamic strategies in.
Hope this helps 🤙
No comments yet…