有什么方法可以从 Yii2 中的错误消息中隐藏文件系统路径

Is there any way to hide filesystem path from error messages in Yii2

生产服务器上有一个应用程序,有时我需要进行一些快速修改。但是,Yii2 在出错时会显示错误文件的完整文件系统路径。

我唯一知道并尝试过的事情:

  1. defined('YII_DEBUG') or define('YII_DEBUG', false);

  2. 一样在web\index.php中停止调试
  3. 暂时关闭网站,如 that,或 public(通过更改 IIS 中的绑定)并通过服务器远程桌面的内部循环访问它。

我想知道是否有任何方法可以让 Yii 停止考虑文件的完整系统路径并考虑一些通用路径,例如 @app\views\site\index.php 而不是 C:\www\app\views\site\index.php

我发现负责显示错误的方法是 renderCallStackItem,它位于 vendor\yiisoft\yii2\web\ErrorHandler.php 中。我刚刚更改了它 returns 的文件参数,如下所示:

public function renderCallStackItem($file, $line, $class, $method, $args, $index)
    {
        $lines = [];
        $begin = $end = 0;
        if ($file !== null && $line !== null) {
            $line--; // adjust line number from one-based to zero-based
            $lines = @file($file);
            if ($line < 0 || $lines === false || ($lineCount = count($lines)) < $line) {
                return '';
            }

            $half = (int) (($index === 1 ? $this->maxSourceLines : $this->maxTraceSourceLines) / 2);
            $begin = $line - $half > 0 ? $line - $half : 0;
            $end = $line + $half < $lineCount ? $line + $half : $lineCount - 1;
        }

        return $this->renderFile($this->callStackItemView, [
            'file' => str_replace(Yii::$app->basePath, '...',$file), //Change is here
            'line' => $line,
            'class' => $class,
            'method' => $method,
            'index' => $index,
            'lines' => $lines,
            'begin' => $begin,
            'end' => $end,
            'args' => $args,
        ]);
    }

我已使用 str_replace 从错误消息中删除应用程序的 basePath。我通过在框架源代码中对文件进行硬编码来完成此操作。

现在的问题,我不知道如何覆盖OOP中的方法?即我想创建从 vendor\yiisoft\yii2\web\ErrorHandler.php 扩展的新 ErrorHandler class。 问题是我如何才能让 Yii2 为整个应用程序更改其 ErrorHandler class?

解决方案如下:

1- 更改 config/web.php\

中的默认 ErrorHandler class
'errorHandler' => [
            'errorAction' => 'site/error',
            'class' => 'app\components\saidbakr\FoxErrorHandler',
        ],
  1. 使用以下代码在 components/saidbakr 中创建一个名为 FoxErrorHandler.php 的新 class:

نتامعلخعرؤنلبغ́خا

<?php
namespace app\components\saidbakr;

use Yii;

class FoxErrorHandler extends \yii\web\ErrorHandler
{
  public function renderCallStackItem($file, $line, $class, $method, $args, $index)
    {
        $lines = [];
        $begin = $end = 0;
        if ($file !== null && $line !== null) {
            $line--; // adjust line number from one-based to zero-based
            $lines = @file($file);
            if ($line < 0 || $lines === false || ($lineCount = count($lines)) < $line) {
                return '';
            }

            $half = (int) (($index === 1 ? $this->maxSourceLines : $this->maxTraceSourceLines) / 2);
            $begin = $line - $half > 0 ? $line - $half : 0;
            $end = $line + $half < $lineCount ? $line + $half : $lineCount - 1;
        }

        return $this->renderFile($this->callStackItemView, [
            'file' => str_replace(Yii::$app->basePath, '...',$file),//Look Here
            'line' => $line,
            'class' => $class,
            'method' => $method,
            'index' => $index,
            'lines' => $lines,
            'begin' => $begin,
            'end' => $end,
            'args' => $args,
        ]);
    }
}

以上class代码只是继承自ErrorHandler,方法renderCallStackItem是对原始方法的复制,对$file值稍作修改。

更新

在某些情况下,错误或调试消息的 header 可能包含受影响文件的完整文件系统路径。它是一个名为 previuosExceptionView 的模板,它在 ErrorHandler class 中有一个名为 previousExceptionView 的 属性。我们应该在 children 错误处理程序 class FoxErrorHandler 中覆盖此 属性,如下所示:

...
class FoxErrorHandler extends \yii\web\ErrorHandler
{
  public $previousExceptionView = '@app/components/saidbakr/previousException.php';
  
  public function renderCallStackItem($file, $line, $class, $method, $args, $index)
    {
....

然后,在 $previousExceptionView 的考虑路径中,我们应该将一个名为 previousException.php 的文件从 \vendor\yiisoft\yii2\views\errorHandler 复制到该路径,即 @app/components/saidbakr/previousException.php,然后我们必须编辑它文件路径输出,文件 previousException.php 应如下所示:

<?php
/* @var $exception \yii\base\Exception */
/* @var $handler \app\components\saidbakr\FoxErrorHandler */
?>
<div class="previous">
    <span class="arrow">&crarr;</span>
    <h2>
        <span>Caused by:</span>
        <?php $name = $handler->getExceptionName($exception);
            if ($name !== null): ?>
            <span><?= $handler->htmlEncode($name) ?></span> &ndash;
            <?= $handler->addTypeLinks(get_class($exception)) ?>
        <?php else: ?>
            <span><?= $handler->htmlEncode(get_class($exception)) ?></span>
        <?php endif; ?>
    </h2>
    <h3><?= nl2br($handler->htmlEncode($exception->getMessage())) ?></h3>
    <!-- in the next line we are going to remove the full filesystem path and replace it with triple dots -->
    <p>in <span class="file"><?= str_replace(Yii::$app->basePath, '...',$exception->getFile()) ?></span> at line <span class="line"><?= $exception->getLine() ?></span></p>
<!-- End Edit -->
    <?php if ($exception instanceof \yii\db\Exception && !empty($exception->errorInfo)) {
        echo '<pre>Error Info: ' . print_r($exception->errorInfo, true) . '</pre>';
    } ?>
    <?= $handler->renderPreviousExceptions($exception) ?>
</div>