仅在 Laravel 5 中为一个环境启用全局中间件
Posted
技术标签:
【中文标题】仅在 Laravel 5 中为一个环境启用全局中间件【英文标题】:Enable global middleware only for one environment in Laravel 5 【发布时间】:2015-04-11 17:35:59 【问题描述】:我在 Laravel 5 (barryvdh/laravel-cors) 中使用了一个全局中间件,但我只希望它在一个环境 (dev) 上处于活动状态。那是因为我只需要在开发环境中与作曲家一起使用它,所以它没有安装在生产环境中。
我在 App Kernel 中注册了它有一个全局中间件,因此如果我尝试在生产中部署我的应用程序,我会遇到错误 (Class 'Barryvdh\Cors\CorsServiceProvider' not found
)。我知道为什么,但我正在寻找解决方案。
有没有办法在 laravel 5 中全局声明一个中间件,但只在一个环境中需要?
我希望它足够清楚,如果没有,我可以编辑我的帖子:)
【问题讨论】:
【参考方案1】:我是 SO 新手,所以我不能评论其他答案。我知道这是一个老话题,但感谢搜索,您仍然可以找到它。
在接受的用户询问的答案中:
当我在 app/Http/Kernel.php 中尝试此操作时,我得到 (!) 致命错误:在 /home/vagrant/earthport/vendor 中出现消息“Class App\Http\Application 不存在”的未捕获异常“ReflectionException” /laravel/framework/src/Illuminate/Container/Container.php 836行
我也有这个问题,基本上你只需要确保包含类
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Routing\Router;
【讨论】:
【参考方案2】:我知道我参加聚会有点晚了,但我想贡献一些我在研究同样的问题时学到的东西。只有在关闭调试模式时,我才尝试应用Spatie's Response Cache 包(这样在我开发时,我不必经常清除缓存以查看更新)。我想将\Spatie\ResponseCache\Middlewares\CacheResponse
中间件应用到web
中间件组。为此,我遵循了@ralpowino 的建议,但做了以下更改:
AppServiceProvider.php
<?php
namespace App\Providers;
use App\Http\Kernel;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
public function boot(Kernel $kernel)
if (!env('APP_DEBUG'))
$kernel->appendMiddlewareToGroup('web', '\Spatie\ResponseCache\Middlewares\CacheResponse');
希望这对某人有所帮助。
附:我意识到有很多方法可以实现我上面解释的目标,例如自定义文档中的 Spatie 缓存配置文件。我只是觉得这更干净一些。
【讨论】:
【参考方案3】:要实现这一点,只需在服务提供者中加载内核,然后调用pushMiddleware
或prependMiddleware
class AppServiceProvider extends ServiceProvider
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(Kernel $kernel)
if ($this->app->environment() === 'dev')
$kernel->prependMiddleware(ClockworkMiddleware::class);
【讨论】:
【参考方案4】:我有与您相反的疑问 - 希望在全球范围内实施中间件,而不是在本地开发中。我尝试了 EspadaV8 推荐的 __construct() 方法,但它确实对我有用,因为 env('APP_ENV') 无法返回我可以测试的值。
我所做的是将我的中间件包含在 Kernel $middleware 数组中,然后在我的中间件的 handle($request, Closure $next)
方法中,我将我的所有代码(return $next($request);
除外)括在括号中:
if(env('APP_ENV') !== 'local')
.......middleware code.......
也许相反的情况对你有用(即 === 而不是 !==)?
我怀疑这不是最好的解决方案 - 正如您所指出的,在内核类中处理中间件的加载(或不加载)是理想的,但我想代替找到更好的东西把这个解决方案放在那里。希望对您有所帮助!
【讨论】:
【参考方案5】:目前我发现的最好方法是检查内核中的 env('APP_ENV')
public function __construct(Application $app, Router $router)
if (env('APP_ENV', 'production') === 'local')
$this->prependMiddleware('Clockwork\Support\Laravel\ClockworkMiddleware');
parent::__construct($app, $router);
【讨论】:
当我在 app/Http/Kernel.php 中尝试此操作时,我得到 (!) 致命错误:未捕获的异常 'ReflectionException' 与 /home/ 中的消息 'Class App\Http\Application 不存在' vagrant/earthport/vendor/laravel/framework/src/Illuminate/Container/Container.php 在第 836 行 应该是App::isLocal()
。【参考方案6】:
在 kernel.php 文件中
//...
protected middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
(!$this->app->environment('local')) ?: 'Path/To/Package'
]
这应该可以解决。
【讨论】:
谢谢。我不能在这里使用“$this”:/ $app-> ... 或者只是 app()-> 您不能在类的内联属性声明中使用除常量值之外的任何内容。但是,您可以轻松地实现一个构造函数来设置此值,然后调用父构造函数以上是关于仅在 Laravel 5 中为一个环境启用全局中间件的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 5.3:如何在全局中间件中使用 Check Auth?