【问题标题】:How to log PHP errors into PHP's error file in Zend Expressive?如何在 Zend Expressive 中将 PHP 错误记录到 PHP 的错误文件中?
【发布时间】:2018-07-19 05:46:35
【问题描述】:

使用 Zend Expressive 2.0.5,我想将 PHP 错误记录到 PHP 的错误日志文件中,我通过 https://docs.zendframework.com/zend-expressive/features/error-handling/#handling-exceptions-and-errors

我也看到了这个帖子:Zend expressive - php error reporting。这为我清除了很多东西,但仍然没有解决所提出的问题。

我所做的事情:定义了我自己的ErrorHandlerFactory,我将两个听众附加到Zend-stratigility's ErrorHandler

  1. First Listener 使用 Zend Log 登录到我的应用程序的日志 文件。(只是认为在我的文件中有错误会很好 application.log 也是。)

  2. 在第二个监听器中,我想登录到PHP的错误日志文件,所以我使用了php中的error_log()方法。

问题:

  1. error_log() 不会像 php 的错误处理程序打印日志时那样打印日志。我的意思:

    当 php 的错误处理程序打印错误时,它看起来像这样:

    [08-Feb-2018 08:22:51 US/Central] PHP 警告:array_push() 预计 至少 2 个参数,1 个在 C:\webserver\webroot\myapi\src\App\src\Action\PageAction.php 上 第 38 行

    当我使用error_log() 打印日志时,它看起来像这样:

    [08-Feb-2018 09:03:49 US/Central] array_push() 预计至少 2 参数,1给出 C:\webserver\webroot\myapi\src\App\src\Action\PageAction.php 上 第 38 行

    我在这里缺少的是 PHP 的错误类型:PHP 警告,这是错误代码吗?我得到的错误代码是一个整数,我该如何解析该代码?我是否应该将错误代码与出现在日志中的 PHP 错误常量进行映射,例如:WARNING、NOTICE 等,我什至可以这样做,但问题是:我得到了相同的错误代码0 php 的错误处理程序打印 警告和致命错误日志的时间。

  2. 这样在 PHP 的错误日志文件中记录错误是否正确?应该 我做 PHP 的错误处理程序的工作?错误处理程序可能会做很多事情,例如:记录少数错误的错误消息,但另一个也记录堆栈跟踪。 如果这不正确,那么我还能如何将错误发送到 PHP 的 error_handler?

    据我了解:

    我自己的错误处理程序阻止用户查找异常和堆栈 跟踪,而是返回一个 通用消息。这也意味着错误处理程序会消耗错误并且不会将其抛到更远的地方,即不会抛出它 到 PHP 的错误处理程序。

【问题讨论】:

    标签: php logging zend-framework mezzio


    【解决方案1】:

    回答问题 1:

    我几乎可以模拟 PHP 错误处理程序记录 PHP 错误的方式。 我做过的事情:

    1. 通过docsthis SO 问题。使用这些我能够将侦听器附加到 Zend-stratigility 的 ErrorHandler
    2. 查看了 PHP 的 Error Constantsset_error_handler(),这让我对如何找出发生了哪种类型的错误或异常有了一些想法。

    下面是我附加侦听器的 ErrorHandlerFactory 的代码。

    <?php
    // TODO: PHP 7.0.8 is giving strict erros eben if this directive is not enabled. And that too, it should be enabled per file from my understanding.
    //declare(strict_types = 1);
    namespace App\Factories;
    use Interop\Container\ContainerInterface;
    use Psr\Http\Message\RequestInterface;
    use Psr\Http\Message\ResponseInterface;
    use Zend\Log\Logger as ZendLogger;
    use Throwable;
    use Zend\Diactoros\Response;
    use Zend\Expressive\Middleware\ErrorResponseGenerator;
    use Zend\Stratigility\Middleware\ErrorHandler;
    class ErrorHandlerFactory
    {
        /**
         * @param ContainerInterface $container
         * @return ErrorHandler
         * @throws \Psr\Container\ContainerExceptionInterface
         * @throws \Psr\Container\NotFoundExceptionInterface
         */
        public function __invoke(ContainerInterface $container)
        {
            $generator = $container->has(ErrorResponseGenerator::class)
                ? $container->get(ErrorResponseGenerator::class)
                : null;
            $errorHandler = new ErrorHandler(new Response(), $generator);
    
             // attaching a listener for logging into application's log file.
            if ($container->has(ZendLogger::class)) {
                /** @var ZendLogger $logger */
                $logger = $container->get(ZendLogger::class);
                $errorHandler->attachListener(function (
                    Throwable $throwable,
                    RequestInterface $request,
                    ResponseInterface $response
                ) use ($logger) {
                    $logger->err(NULL, [
                        'method'  => $request->getMethod(),
                        'uri'     => (string) $request->getUri(),
                        'message' => $throwable->getMessage(),
                        'file'    => $throwable->getFile(),
                        'line'    => $throwable->getLine(),
                    ]);
                });
            }
    
            // Attaching second listener for logging the errors into the PHP's error log
            $errorHandler->attachListener(function (
                Throwable $throwable,
                RequestInterface $request,
                ResponseInterface $response
            ) {
                // Default Error type, when PHP Error occurs.
                $errorType = sprintf("Fatal error: Uncaught %s", get_class($throwable));
                if (get_class($throwable) === "ErrorException") {
    
                    // this is an Exception
                    /** @noinspection PhpUndefinedMethodInspection */
                    $severity = $throwable->getSeverity();
                    switch($severity) {
                        case E_ERROR:
                        case E_USER_ERROR:
                            $errorType = 'Fatal error';
                            break;
                        case E_USER_WARNING:
                        case E_WARNING:
                            $errorType = 'Warning';
                            break;
                        case E_USER_NOTICE:
                        case E_NOTICE:
                        case E_STRICT:
                            $errorType = 'Notice';
                            break;
                        case E_RECOVERABLE_ERROR:
                            $errorType = 'Catchable fatal error';
                            break;
                        case E_USER_DEPRECATED:
                        case E_DEPRECATED:
                            $errorType = "Deprecated";
                            break;
                        default:
                            $errorType = 'Unknown error';
                    }
    
                    error_log(sprintf("PHP %s: %s in %s on line %d", $errorType, $throwable->getMessage(), $throwable->getFile(), $throwable->getLine()), 0);
                }
                else {
                    // this is an Error.
                    error_log(sprintf("PHP %s: %s in %s on line %d \nStack trace:\n%s", $errorType, $throwable->getMessage(), $throwable->getFile(), $throwable->getLine(), $throwable->getTraceAsString()), 0);
                }
            });
    
            return $errorHandler;
        }
    }
    

    除此之外,还需要将这个工厂添加到依赖项中。 在文件中: dependencies.global.php,在factories数组中:

    替换

    Zend\Stratigility\Middleware\ErrorHandler::class =&gt; Container\ErrorHandlerFactory::class,

    Zend\Stratigility\Middleware\ErrorHandler::class => \App\Factories\ErrorHandlerFactory::class
    

    这应该几乎可以模拟 php 错误处理程序的日志记录行为。

    回答问题 2:

    我认为这样做很好,因为 PHP 本身提供了set_error_handler(),而且无论如何我们必须自己处理错误,而不是将其传递给 PHP 的错误处理程序。如果我们的 ErrorHandler(listener) 可以复制消息并使用error_log() 登录到 PHP 的错误日志中,那就没问题了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      相关资源
      最近更新 更多