Отвечая на вопрос 1:
Я могу почти имитировать способ, которым обработчик ошибок PHP регистрирует ошибки PHP. Что я сделал:
- Просмотрел документы и этот ТАК вопрос. Используя их, я смог подключить слушателей к Zend-stratigility ErrorHandler.
- Прошелся по константам ошибок и set_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 => Container\ErrorHandlerFactory::class,
с участием
Zend\Stratigility\Middleware\ErrorHandler::class => \App\Factories\ErrorHandlerFactory::class
И это должно почти имитировать поведение ведения журнала, как это делает обработчик ошибок php.
Ответ на вопрос 2:
Я думаю, что это нормально, поскольку PHP сам по себе предоставляет set_error_handler()
, и в любом случае мы должны сами обрабатывать ошибки, а не передавать их обработчику ошибок PHP. Если наш ErrorHandler(слушатель) может реплицировать сообщения и войти в журнал ошибок PHP, используя error_log()
, тогда все в порядке.
person
Ashish Ranjan
schedule
09.02.2018