Laravel 5.7 如何使用 URL 记录 404

Laravel 5.7 How to Log 404 With URL

我想在 Laravel 5.7 中记录 404 错误,但我不知道如何打开它。除了记录 404 错误之外,我还想记录所请求的 URL。其他错误已正确记录。

.env

APP_DEBUG=true
LOG_CHANNEL=stack

config/logging.php

'stack' => [
    'driver' => 'stack',
    'channels' => ['daily'],
],

根据 Error Handling documentation:

The $dontReport property of the exception handler contains an array of exception types that will not be logged. For example, exceptions resulting from 404 errors, as well as several other types of errors, are not written to your log files. You may add other exception types to this array as needed:

app/Exceptions/Handler 中,$dontReport 数组为空。

我已经通过 Blade 文件自定义了 404 视图 resources/views/errors/404.blade.php

基于 我已经在 app/Exceptions/Handler, 中尝试过此代码,但日志中没有显示任何内容:

public function report(Exception $exception)
{
    if ($this->isHttpException($exception)) {
        if ($exception instanceof NotFoundHttpException) {
            Log::warning($message);
            return response()->view('error.404', [], 404);
        }
        return $this->renderHttpException($exception);
    }

    parent::report($exception);
}

在接受 Mozammil 的回答后更新,效果很好。 我已经缩短了他对下面的回答。不要忘记将 use Illuminate\Support\Facades\Log 添加到处理程序文件中。

public function render($request, Exception $exception)
{
    if ($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
        Log::warning('404: ' . $request->url());
        return response()->view('errors.404', [], 404);
    }
    return parent::render($request, $exception);
}

我也有类似的需求。这是我实现它的方式。

我有一个辅助方法来确定它是否是 404。

private function is404($exception)
{
    return $exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException
            || $exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
}

我还有另一种方法来实际记录 404。

private function log404($request) 
{
    $error = [
        'url'    => $request->url(),
        'method' => $request->method(),
        'data'   => $request->all(),
    ];

    $message = '404: ' . $error['url'] . "\n" . json_encode($error, JSON_PRETTY_PRINT);

    Log::debug($message);
}

然后,为了记录错误,我只是在 render() 方法中做了这样的事情:

public function render($request, Exception $exception)
{
    if($this->is404($exception)) {
        $this->log404($request);
    }

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

我不知道 $internalDontReport。但是,在所有情况下,我的实施对我都有效 :)

我用Telescope

Laravel Telescope
Laravel Telescope 是 Laravel 框架的优雅调试助手。 Telescope 深入了解进入您的应用程序的请求、异常、日志条目、数据库查询、排队的作业、邮件、通知、缓存操作、计划任务、变量转储等。

https://laravel.com/docs/5.7/telescope

我注意捕捉所有类型的 4xx 错误,所以我在 app/Exceptions/Handler.php 文件中进行编辑,在渲染函数中添加以下代码

if($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException ||
        $exception instanceof \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException ||
        $exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException){
        $error = [
            'message'=> $exception->getMessage(),
            'type'   => \get_class($exception),
            'url'    => $request->url(),
            'method' => $request->method(),
            'data'   => $request->all(),
        ];

        $message = $exception->getStatusCode().' : ' . $error['url'] . "\n" . \json_encode($error, JSON_PRETTY_PRINT);
        //Store the object in DB or log file
        \Log::debug($message);
    }

此代码将捕获 [ModelNotFoundException、MethodNotAllowedHttpException、NotFoundHttpException] 的异常 - 简而言之,这将捕获 404 错误、在数据库中找不到模型和错误的方法 - 并创建一个名为 $error 的对象,您将能够将它存储在任何你想要的地方。

所以 app/Exceptions/Handler.php 会像

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Throwable  $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $exception)
    {

        if($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException ||
            $exception instanceof \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException ||
            $exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException){
            $error = [
                'message'=> $exception->getMessage(),
                'type'   => \get_class($exception),
                'url'    => $request->url(),
                'method' => $request->method(),
                'data'   => $request->all(),
            ];

            $message = $exception->getStatusCode().' : ' . $error['url'] . "\n" . \json_encode($error, JSON_PRETTY_PRINT);

            \Log::debug($message);
        }
        return parent::render($request, $exception);
    }
}

P.S。我正在使用 laravel 8,但我确信它适用于大多数流行的版本。