[英]How to log PHP errors into PHP's error file in Zend Expressive?
Using Zend Expressive 2.0.5, I want to log PHP errors into the PHP's error log file itself, I went through https://docs.zendframework.com/zend-expressive/features/error-handling/#handling-exceptions-and-errors 使用Zend Expressive 2.0.5,我想将PHP错误记录到PHP的错误日志文件本身中,我经历了https://docs.zendframework.com/zend-expressive/features/error-handling/#handling-exceptions-和-errors
I also saw this post: Zend expressive - php error reporting . 我也看到了这篇文章: Zend expressive-php error report 。 Which cleared a lot of things for me but still quite didn't solve the asked question.
这为我清除了很多东西,但仍然没有解决所提出的问题。
Things I did: Defined my own ErrorHandlerFactory
where I attached two listeners to the Zend-stratigility's ErrorHandler
我所做的事情:定义了我自己的
ErrorHandlerFactory
,在其中我将两个侦听器附加到Zend-stratigility's ErrorHandler
First Listener uses Zend Log to log into my application's log file.(Just thought it would be nice to have errors in my application.log too.) First Listener使用Zend Log登录到我的应用程序的日志文件中(只是认为在我的application.log中也有错误也很好。)
In the Second Listener, I want to log into PHP's error log file, so I have used error_log()
method from php. 在第二侦听器中,我想登录到PHP的错误日志文件,因此我使用了php中的
error_log()
方法。
Questions: 问题:
The error_log() is not printing the log the way a log appears when printed by php's error handler. error_log()不能像使用php的错误处理程序打印日志时那样显示日志。 What I mean:
我的意思是:
When an error is printed by the php's error handler, it looks something like this: 当错误由php的错误处理程序打印时,它看起来像这样:
[08-Feb-2018 08:22:51 US/Central] PHP Warning: array_push() expects at least 2 parameters, 1 given in C:\\webserver\\webroot\\myapi\\src\\App\\src\\Action\\PageAction.php on line 38
[2018年2月8日08:22:51美国/中部] PHP警告:array_push()至少需要2个参数,其中1个在C:\\ webserver \\ webroot \\ myapi \\ src \\ App \\ src \\ Action \\ PageAction.php中给出在第38行
While when I print the log using error_log()
it looks something like this: 当我使用
error_log()
打印日志时,它看起来像这样:
[08-Feb-2018 09:03:49 US/Central] array_push() expects at least 2 parameters, 1 given in C:\\webserver\\webroot\\myapi\\src\\App\\src\\Action\\PageAction.php on line 38
[2018年2月8日09:03:49美国/中部] array_push()至少需要2个参数,第38行的C:\\ webserver \\ webroot \\ myapi \\ src \\ App \\ src \\ Action \\ PageAction.php中提供1个参数
What am I missing here is the PHP's error type: PHP Warning , Is this the error code? 我在这里缺少的是PHP的错误类型: PHP警告 ,这是错误代码吗? The error code I get is an integer, how do I parse that code?
我得到的错误代码是整数,如何解析该代码? should I map the error codes with PHP errors constants which appear in the logs, for example: WARNING, NOTICE, etc , I can even do that, but the problem is: I got the same error code of 0 both the times when php's error handler printed a WARNING and a Fatal error logs.
我应该将错误代码与出现在日志中的PHP错误常量进行映射,例如: WARNING,NOTICE等 ,但我什至可以这样做,但是问题是:当php错误时,我两次都得到了相同的错误代码0处理程序打印警告和致命错误日志。
Is it right to log errors in PHP's error log file like this? 这样在PHP的错误日志文件中记录错误是否正确? Should I do the job of PHP's error handler?
我应该做PHP的错误处理程序吗? The error handler could be doing a lot of things, for example: Logging the error message for few errors but for another also logging the stack trace.
错误处理程序可能会做很多事情,例如:记录错误消息中的几个错误,但记录另一个错误也记录堆栈跟踪。 If this is not right, then how else can I send the error to the PHP's error_handler?
如果这不正确,那么我该如何将错误发送给PHP的error_handler?
From my understanding: 据我了解:
My own Error Handler prevents users to look for exceptions and stack traces but rather returns a generic message.
我自己的错误处理程序可防止用户查找异常和堆栈跟踪,而是返回通用消息。 This also means that the Error Handler consumes the error and doesn't throw it further outside, ie will not throw it to the PHP's error handler.
这也意味着错误处理程序会使用该错误,并且不会将其进一步抛出外部,即不会将其抛出给PHP的错误处理程序。
Answering question 1: 回答问题1:
I am able to almost simulate the way PHP error handler logs PHP errors. 我几乎可以模拟PHP错误处理程序记录PHP错误的方式。 Things I did:
我所做的事情:
Below is the code for my ErrorHandlerFactory where I attach the listeners. 以下是我在其中附加侦听器的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;
}
}
Apart from this, this Factory needs to be added to the dependencies. 除此之外,还需要将此工厂添加到依赖项中。 In the file:
dependencies.global.php
, in the factories
array: 在
factories
数组中的文件: dependencies.global.php
中:
Replace 更换
Zend\\Stratigility\\Middleware\\ErrorHandler::class => Container\\ErrorHandlerFactory::class,
with 同
Zend\Stratigility\Middleware\ErrorHandler::class => \App\Factories\ErrorHandlerFactory::class
And this should almost simulate the logging behaviour how php error handler does. 并且这几乎可以模拟php错误处理程序的日志记录行为。
Answering Question 2: 回答问题2:
I think it is fine to do this since PHP by itself provides set_error_handler()
and anyway we have to handle the errors by ourselves and not pass it to the PHP's error handler. 我认为这样做很好,因为PHP本身提供了
set_error_handler()
而且无论如何我们都必须自己处理错误,而不是将其传递给PHP的错误处理程序。 If our ErrorHandler(listener) can replicate the messages and log into the PHP's error log using error_log()
, then it is fine. 如果我们的ErrorHandler(listener)可以复制消息并使用
error_log()
登录到PHP的错误日志中,那么就可以了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.