PHP の致命的なエラー (通知と警告も含む) をキャプチャし、Monolog を使用してそれらをログに記録する方法が必要です。
Monolog 1.6+ には ErrorHandler::register() メソッドがあることがわかりましたが、Symfony2 (本番) アプリケーションでの使用方法と、config.yml での適切な構成方法がわかりません。
正しい方向を示してくれた@jenechkaのおかげで、解決策を見つけたと思います。
services.yml:
vir.exception.listener:
class: %vir.exception.listener.class%
arguments: ["@logger"]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
エラーハンドラ:
<?php
namespace Mitecube\VoglioilruoloBundle\Listener;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Psr\Log\LoggerInterface;
class VoglioilruoloErrorHandler extends ErrorHandler {
private $logger;
private $prevErrorHandler;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
$this->prevErrorHandler = set_error_handler(array($this, 'handle'));
register_shutdown_function(array($this, 'handleFatal'));
}
public function onKernelRequest(GetResponseEvent $event)
{
}
public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
{
$this->logger->error($level . ": " . $message . " - in file " . $file . " - at line " . $line);
return parent::handle($level, $message, $file, $line, $context);
}
}
このようにして、各エラーをモノログに記録できます。この解決策は「ベスト プラクティス」とは考えられないため、より良い解決策を探しています。
ここで説明されているように例外リスナーを作成しますhttp://symfony.com/doc/current/cookbook/service_container/event_listener.html
そして、ここを参照してください http://symfony.com/doc/current/reference/dic_tags.html#monolog-logger logger を引数としてリスナーに送信する方法
サービスの構成例:
# src/Acme/DemoBundle/Resources/config/services.yml
parameters:
# ...
services:
# ...
kernel.listener.your_listener_name:
class: Acme\DemoBundle\EventListener\AcmeExceptionListener
arguments: ["@logger"]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
- { name: monolog.logger, channel: tema }
リスナーの例:
// src/Acme/DemoBundle/EventListener/AcmeExceptionListener.php
namespace Acme\DemoBundle\EventListener;
use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Psr\Log\LoggerInterface;
class ExceptionListener extends ExceptionHandler
{
private $logger;
private $prevExceptionHandler;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
// Set our handle method as fatal exception handler.
// It is required to extend Symfony\Component\Debug\ExceptionHandler
$this->prevExceptionHandler = set_exception_handler(array($this, 'handle'));
}
public function onKernelRequest(GetResponseEvent $event)
{
}
/**
* Handles non fatal exceptions (normal way).
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
// You get the exception object from the received event
$exception = $event->getException();
// Log exception.
$this->logger->error($exception->getMessage());
// ...
}
/**
* Overwrite ExceptionHandler method.
*/
public function handle(\Exception $exception) {
// Call our custom handler.
$this->onFatalErrorException($exception);
// Call exception handler that was overridden.
// Or try to call parent::handle($exception)
if (is_array($this->prevExceptionHandler) && $this->prevExceptionHandler[0] instanceof ExceptionHandler) {
$this->prevExceptionHandler[0]->handle($exception);
}
}
public function onFatalErrorException(\Exception $exception)
{
// Do anything you want...
$this->logger->error('Hey, I got it: '. $exception->getMessage());
}
}
更新: 例外リスナーを改善し、致命的な例外を処理するようになりました。テスト済み(開発環境)!