仅在 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】:

要实现这一点,只需在服务提供者中加载内核,然后调用pushMiddlewareprependMiddleware

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?

如何仅在 Spring 中为微服务项目的外部客户端启用身份验证?

无法在 Laravel 5 中为特定路线添加 CORS

仅在网格(WPF)中为一行添加IsEnabled

在中间人中为视频启用资产管道

身份验证问题 Laravel 5.2 登录仅在本地工作