【问题标题】:Disable error reporting entirely in Laravel production? [duplicate]在 Laravel 生产中完全禁用错误报告? [复制]
【发布时间】:2017-12-02 01:17:05
【问题描述】:

我想在生产环境中完全禁用错误报告,因为我们有一些非常旧的代码仍然需要修复,但现在可以正常工作(是的,我也不喜欢它)。我们无法在几天内解决所有问题,因此我们需要像往常一样抑制警告和异常。

真正的问题是它已经在一个简单的惰性 bug 上抛出异常(因为没有定义 var)

if(!$var) {
     // do whatever
}

试过

APP_DEBUG=false

APP_LOG_LEVEL=紧急情况

display_errors(false);
set_error_handler(null);
set_exception_handler(null);

但它仍然显示ErrorException

未定义变量:script_name_vars_def

编辑:代码是这样工作的

web.php

Route::any('/someroute', 'somecontroller@controllerFunc');

somecontroller.php

public controllerFunc() {
    ob_start();
    require '/old_index.php';
    $html = ob_get_clean();

    return response($html);
}

这样我们就可以使用 Laravel 路由,而不必立即重写旧代码。

我知道我可以很容易地修复这个警告,但是这些错误还有很多很多,我们现在需要使用 Laravel 路由。稍后解决问题。

想法

编辑以说明中间件在哪些步骤之后不起作用

1) 创建中间件

php artisan make:middleware SuppressExceptions

2) 写出来

SuppressExceptions.php

public function handle($request, Closure $next)
{
    error_reporting(0);
    return $next($request);
}

3) 注册

laravel/app/Http/Kernel.php

protected $middlewareGroups = [
   'web' => [
       \App\Http\Middleware\SuppressExceptions::class,
],

【问题讨论】:

  • 你试过APP_DEBUG=false吗?
  • 是的,我的问题打错了,抱歉。我再次启用它来复制和粘贴警告:)
  • 好吧,如果你设置 APP_DEBUG=false 并且它仍然显示包含所有信息的错误页面,请考虑清除缓存。如果发生错误,则无法抑制错误页面,除非您使用 try/catch 覆盖所有功能并可能重定向
  • 不,那么它只显示Whoops, looks like something went wrong.
  • 很抱歉,直到星期一我才能访问代码 :)

标签: php laravel laravel-5 laravel-5.3 laravel-5.4


【解决方案1】:

是的,您可以更改错误报告。实际上,框架提供了一个拦截异常的地方:App\Exceptions\Handler。默认情况下,render 方法会将抛出的异常转换为 HTML 响应。 APP_ENVAPP_DEBUG 值只会改变此错误响应的呈现方式(基本上是否有异常堆栈跟踪的详细信息)。

尝试将render 方法更改为

public function render($request, Exception $exception)
{
    if ($exception instanceof ErrorException) {
        error_reporting(0);

        $kernel = app(\Illuminate\Contracts\Http\Kernel::class);
        $response = $kernel->handle($request)->send();
        return $kernel->terminate($request, $response);
    }

    return parent::render($request, $exception);
}

这基本上会关闭报告,然后尝试重新处理请求。 在if 子句中,您可以检查您想要的任何条件(异常类别、严重性等)。捕获ErrorException 可能会满足您的需求,但请注意,您可能无法通过这种方式从致命错误中恢复。

无论如何,您应该将其视为“概念证明”......对于非幂等请求,这种“重新处理”方法并不好。相反,只需 create a Middleware

public function handle($request, Closure $next)
{
    error_reporting(0);
    return $next($request);
}

和以前一样,无法通过这种方式恢复致命错误。但是您可以将此中间件与之前的异常处理程序方法结合起来显示自定义错误消息:

public function render($request, Exception $exception)
{
    if ($exception instanceof FatalErrorException) {
        return view('fatal-error', ['exception' => $exception]);
    }

    return parent::render($request, $exception);
}

【讨论】:

  • @ThomasMoors 什么是“没用”?您一直看到“哎呀”消息?有什么例外?使用这种方法,我尝试并成功忽略了一些错误,例如未定义的变量或除以零
  • 是的,它确实会不断显示每一个错误。我将编辑我的问题以解释我从您的回答中尝试的步骤。
  • @ThomasMoors 看到了您的编辑。这正是我所拥有的。您确定该路线在web 组中吗?尝试在中间件方法中执行dd(something);,以确保它正在应用。
  • 是的,我很肯定,您是否结合我在 somecontroller.php 中使用ob_get_clean 编写的代码测试了您的设置?它可能会产生不同的结果
  • @ThomasMoors 等等,你确定不是 require 失败了吗?使用require '/old_index.php';,您正在文件系统的根目录中查找文件。你在哪里有它?
【解决方案2】:

Laravel 调试设置位于.env 文件中,您可以在其中设置调试选项如下:

APP_DEBUG = true

但是……

Laravel 也有配置机制,位于 app.php 文件夹中的 config,默认为:

'debug' => env('APP_DEBUG', false),

告诉 Laravel 使用 .env 值,默认为 false,但任何有权访问该文件的人都可以简单地将其更改为:

'debug' => true,

这样你的 .env 值就会被 Laravel 忽略。

【讨论】:

  • 如果您已经阅读了问题并给出了答案,您可能已经知道或推断出它并不像忘记.env文件的存在那么简单。接下来:env文件优先于配置文件,配置文件是备用值。
  • 同意,但我只是告诉你,它可能会被有权访问配置文件的人更改,就像我声明的最后一点?
  • 不是,即使它是:.env 文件推翻了app.php。你现在满意吗?
  • 您对.env 推翻app.php 有一点错误,因为我声明中的第二点,它推翻了它,如果它被改变,那么行为就会改变。但如果它没有改变,那么适合你自己,没必要生气。我只是假设您正在作为一个团队工作。看来我错了
  • 我确实在一个团队中工作。你激怒我的原因是你给出了一个低质量的答案,你不遗余力地捍卫它是一个好的答案。
【解决方案3】:

我是怎么做的

app/providers/AppServiceProvider 

在开机功能中

public function boot()
{
   //add error reporting level
   error_reporting(0);
}

App Service Provider 在 Laravel 编译之前运行,因此在启动功能中你可以将错误报告设置为任何级别。它将为所有正在运行的脚本设置。您可以打开您的 app/providers/AppServiceProvider.php 并在启动功能中添加 error_reporting(0/1)

【讨论】:

  • 您能否进一步解释一下,以便其他人可以从中学习?
  • App Service Provider 在 Laravel 编译之前运行,因此在启动功能中你可以将错误报告设置为任何级别。它将为所有正在运行的脚本设置。您可以打开您的 app/providers/AppServiceProvider.php 并在启动功能中添加 error_reporting(0/1)
【解决方案4】:

我猜你的php.ini 是从另一个地方加载的。所以设置仍然没有应用。尝试找到php.ini的正确位置(您可以在phpinfo()中查看信息)。无论如何,您可以在index.php 中用您的参数重写这些参数:

error_reporting(0);
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);

但正如@Davon 在评论中所说。这些设置将被 Laravel 覆盖。所以上面的代码可以放在你的控制器中。但这将是肮脏的黑客攻击。所以你必须找到另一种方法。尝试打印您的.env 的内容。可能有些设置不正确。

【讨论】:

  • 这不会对 Laravel 产生影响,因为 Laravel 在应用启动时会重置 error_reporting。
  • @Devon 哦,是的,确实如此。在HandleExceptions 类的bootstrap() 方法中找到它。
【解决方案5】:
error_reporting(0);
ini_set('display_errors', 0);

第二行改变php.ini文件中'display_errors'的值

编辑:添加更多代码以显示这必须是特定于环境的...

$env = getenv('APPLICATION_ENV');

 switch ($env) {
        case 'production':
            error_reporting(0);
            $config = include __DIR__ . '/../app/config/config_prod.php';
            break;

        case 'staging':
            ini_set('display_errors', 1);
            $config = include __DIR__ . '/../app/config/config_staging.php';
            break;

        case 'development':
        case 'local':
        default:
            ini_set('display_errors', 1);
            $config = include __DIR__ . '/../app/config/config_local.php';
            break;

【讨论】:

  • 它对我完全没有影响,它仍然显示Whoops, looks like something went wrong.
  • 你能展示更多你想要实现的代码吗?此外,并不是说这些更改必须是特定于环境的。查看我的编辑
  • 您可能需要考虑使用config('app.env') 获取环境,而不是调用getenv;如果配置被缓存,对getenv 的调用将返回 null 而不是生产、暂存等。
  • 这不会对 Laravel 产生影响,因为 Laravel 在应用启动时会重置 error_reporting,您需要修改核心框架 HandleExceptions.php,如我的示例所示。
【解决方案6】:

如果问题是您看到“哎呀,出了点问题”页面,您可以通过@alepeino 写道的答案来解决这个问题:

https://stackoverflow.com/a/44862789/2777970

但我会将渲染方法更改为:

public function render($request, Exception $exception)
{
    if (!config('app.debug')) {
        error_reporting(0);

        return response('nothing', 500);
    }

    return parent::render($request, $exception);
}

这个渲染方法(父)是为“哎呀”页面构建和返回html的方法,所以如果你覆盖它,你应该很酷。

要更改调试配置,请检查您的 config/app.php 是否具有使用 ENV 值 APP_DEBUG 的调试选项,并在您的生产环境中检查它是否设置为 false (APP_DEBUG=false)。

【讨论】:

  • 关于导致它显示错误的错误,你应该使用if (!isset($var) || !$var) 所以它会在检查它的布尔值之前检查变量是否存在,所以你不会得到错误。但我认为你可能不想解决这个问题,或者它不像你说的那么简单,否则这个问题将是另一个问题
  • 我已经修复了这个“错误”的 1000 多个实例哈哈,顺便说一句,我的解决方案是 $var = $var ?? null
  • 不错,php7 功能
  • 这部分工作:它在到达“错误”时停止呈现页面的其余部分。
  • 但是我不明白,你之前还有内容吗?或者你得到 php 错误?要修复 php 错误,您不应该使用某人告诉的 php.ini 建议来修复它吗? ini_set('display_errors', 0); ?
【解决方案7】:

Laravel 强调没有错误和警告的代码,因此处理这个问题的最佳方法就是确保您的代码不会产生任何错误、警告或通知。

更新:对于最新版本的 Laravel,我不推荐以下方法。 Laravel 现在允许您更改非供应商类中的异常处理: App\Exceptions\Handler 如 alepeino 的回答所示。中间件也是禁用 error_reporting 的更好解决方案。

之前的答案出于历史目的而保留,但我不建议修改供应商文件。


但是,如果您仍然决定更改此行为,则需要查看通常位于 vendor/laravel/framework/src/illuminate/Foundation/Bootstrap/HandleExceptions.php 的名为 HandleExceptions.php 的文件:

public function bootstrap(Application $app)
{
    $this->app = $app;
    error_reporting(-1); // change this line to your desired reporting level
    set_error_handler([$this, 'handleError']);
    set_exception_handler([$this, 'handleException']);
    register_shutdown_function([$this, 'handleShutdown']);
    if (! $app->environment('testing')) {
        ini_set('display_errors', 'Off');
    }
}

第 32 行,error_reporting 当前设置为 -1。 https://github.com/laravel/framework/blob/5.4/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php

当然,通过修改此代码,您要么需要阻止 laravel/framework 的更新,要么需要在每次更新时验证此文件。

更新此代码后,您需要重新编译您的类:

php artisan clear-compiled; php artisan optimize

【讨论】:

  • 我明白,但即使将其更改为 E_ERROR 也没有任何改变
  • 你清除了你的应用缓存和编译的类吗?
  • @ThomasMoors clear-compiled 是你想要的,cache:clear 只涉及缓存的对象,而不是编译的类。
【解决方案8】:

在您的类中的任何函数中使用此方法作为示例:

try {
    // ...
} catch (\Exception $e) {
    return redirect()->intended(route('home'));
}

【讨论】:

    猜你喜欢
    • 2018-12-28
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 2015-04-23
    • 2011-09-05
    • 2017-07-27
    • 2019-04-23
    • 2014-01-13
    相关资源
    最近更新 更多