在Laravel 5中仅为一个环境启用全局中间件

13

我正在使用 Laravel 5 中的全局中间件 (barryvdh/laravel-cors),但我只希望在一个环境 (dev) 中启用它。这是因为我只需要在 dev 环境下通过 composer 安装它,所以它没有被安装在生产环境中。

我在 App Kernel 中注册了它作为全局中间件,所以如果我尝试在生产环境中部署我的应用程序,就会出现错误 (Class 'Barryvdh\Cors\CorsServiceProvider' not found)。我知道原因,但我正在寻找解决方案。

是否有任何方法可以在 Laravel 5 中全局声明中间件,但只在一个环境中要求它?

我希望这足够清楚,如果不清楚,我可以编辑我的帖子 :)

6个回答

9
为了实现这一点,只需在服务提供者中加载内核,然后调用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);
        }
    }
}

1
在 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'
 ]

这应该解决问题。

2
谢谢。我这里不能使用"$this" :/ - rap-2-h
只使用 $app-> ... 或者简单地使用 app()-> 怎么样? - Helder Lucas
在类的内联属性声明中,您不能使用除常量值以外的任何内容。但是,您可以轻松实现一个设置此值并调用父构造函数的构造函数。 - apokryfos

1
到目前为止,我发现最好的方法是在内核中检查 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);
}

1
当我在app/Http/Kernel.php中尝试这样做时,我得到了以下错误:( ! ) 致命错误:ReflectionException异常,消息为“类App\Http\Application不存在”,位于/home/vagrant/earthport/vendor/laravel/framework/src/Illuminate/Container/Container.php的第836行。 - HowApped
4
应该是 App::isLocal() - goyote

1
我是新来的SO用户,所以我没有权限评论其他答案。我知道这是一个老话题,但还是通过搜索找到了它。
在被接受的答案中,一个用户问道:
“当我尝试在app/Http/Kernel.php中执行此操作时,我会得到(!)致命错误:在/home/vagrant/earthport/vendor/laravel/framework/src/Illuminate/Container/Container.php的第836行中,未捕获的异常'ReflectionException',消息为“类App\Http\Application不存在”。
我也遇到了这个问题,基本上你只需要确保包含这些类即可。
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Routing\Router;

0

我有一个与你相反的问题 - 希望在生产环境中全局实现中间件,但在本地开发中不需要。我尝试了EspadaV8推荐的__construct()方法,但它对我没有起作用,因为env('APP_ENV')未返回我可以测试的值。

相反,我将我的中间件包含在Kernel $middleware数组中,然后在我的中间件的handle($request, Closure $next)方法中,除了return $next($request);之外,我将所有代码都用以下内容括起来:

if(env('APP_ENV') !== 'local') { 

.......middleware code.......

}

也许相反的方法适合你(即使用 === 而不是 !==)?

我怀疑这不是最好的解决方案 - 正如你所指出的,理想情况下应该在 Kernel 类中处理中间件的加载(或不加载),但是目前还没有找到更好的解决方案,因此我想提供这个解决方案。希望能有所帮助!


0

我知道我来晚了,但我想贡献一些我在研究这个问题时学到的东西。我试图只在关闭调试模式时应用Spatie's Response Cache包(这样在开发时,我就不必不断清除缓存以查看更新)。我想将\Spatie\ResponseCache\Middlewares\CacheResponse中间件应用于web中间件组。为了做到这一点,我遵循了@ralphowino的建议,但进行了以下更改:

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 缓存配置文件。我只是认为这种方法更加简洁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接