Php 无法捕获全局异常

Php 无法捕获全局异常,php,Php,如果指定的日志文件有问题,Monolog将抛出一个\UnexpectedValueException 在我的代码中,我试图捕获\UnexpectedValueException,但一直无法捕获 我的代码是: <?php namespace myNamespace; use Monolog\Logger as Monolog; use Monolog\Handler\StreamHandler; class Logger { private static $instance;

如果指定的日志文件有问题,Monolog将抛出一个
\UnexpectedValueException

在我的代码中,我试图捕获
\UnexpectedValueException
,但一直无法捕获

我的代码是:

<?php
namespace myNamespace;

use Monolog\Logger as Monolog;
use Monolog\Handler\StreamHandler;


class Logger {

    private static $instance;

    private static function init()
    {
        if (!self::$instance)
        {
            $logger = new Monolog(MY_LOG_CHANNEL);

            try 
            {                
                $logger->pushHandler(new StreamHandler(MY_LOG_PATH . "/" . 
                   MY_LOG_NAME, Monolog::NOTICE));            
            }
            catch (\UnexpectedValueException $e)
            {
                writeln("Error starting logger" . $e->getMessage());
                die;
            }

            // and so on
据我所知,它们已经转移到了全局名称空间,所以我应该能够在那里找到它。为什么我不能?我尝试了名称空间
\mynamespace\UnexpectedValueException
甚至
Monolog\UnexpectedValueException
全局或本地的所有组合,但均无效

很明显我遗漏了什么,请问是什么

编辑:

在另一个类中,我正在执行一个
if(file\u exists($fileName))/**do file\u get\u contents()etc*/else Logger::error($fileName.“not exists”)

当我调用
self::init()

这个错误是因为我(故意)屏蔽了日志文件路径,如果它是一个有效的日志文件路径,那么代码运行正常。很明显,我想捕捉那个错误,因此需要try/catch

跟踪中的下一行是上面代码中的行:
$logger->pushHandler(新的StreamHandler(MY_LOG_路径./”.MY_LOG_名称,Monolog::NOTICE))

有趣的是,如果我故意拼错文件名var、
file\u get\u contents
barfs和一个标准的
catch(Exception$e)
的工作原理与我对
文件获取内容()的预期一样。

这是一个非常古老的问题,可能在这期间得到了解决。但是,为了将来的访问者,我想指出,在将日志条目写入给定文件时,而不是在构建时,会引发异常

按照
try{}catch(){}
设置的方式,在创建
StreamHandler
时会出现异常。然而,当您试图通过调用(如
$logger->error(“error message”)
发送到日志时,真正的异常就会发生,因此您应该在那里捕获异常


另一方面,我认为从日志库抛出异常是最愚蠢的事情之一。日志应该是幂等的,并且不会影响正在运行的应用程序的状态。

在旧的silex应用程序中,我也遇到了这个问题。我想登录到一个logstash实例,但是如果logstash不可用,它就不会中断

幸运的是,我的应用程序只使用了针对
Psr\Log\LoggerInterface
键入的记录器,因此我可以编写一个decorator来防止异常在一个地方破坏应用程序,而不是在代码库中的每个调用上添加try-and-catch调用

看起来是这样的:

<?php

namespace Dreamlines\DirectBookingForm\ServiceProvider;

use Psr\Log\LoggerInterface;

/**
 * DontThrowLoggerDecorator
 *
 * Monolog will break on info, error, etc. calls
 * This decorator wrap the LoggerInterface and ensures that failure to log won't break the app
 **/
class DontThrowLoggerDecorator implements LoggerInterface
{
    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }


    /**
     * @inheritDoc
     */
    public function emergency($message, array $context = array())
    {

        try {
            $this->logger->emergency($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function alert($message, array $context = array())
    {
        try {
            $this->logger->alert($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function critical($message, array $context = array())
    {
        try {
            $this->logger->critical($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function error($message, array $context = array())
    {
        try {
            $this->logger->error($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function warning($message, array $context = array())
    {
        try {
            $this->logger->warning($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function notice($message, array $context = array())
    {
        try {
            $this->logger->notice($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function info($message, array $context = array())
    {
        try {
            $this->logger->info($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function debug($message, array $context = array())
    {
        try {
            $this->logger->debug($message, $context);
        } catch (\Exception $e) {
        }
    }

    /**
     * @inheritDoc
     */
    public function log($level, $message, array $context = array())
    {
        try {
            $this->logger->log($level, $message, $context);
        } catch (\Exception $e) {
        }
    }
}
$app['NOT_BREAKING_LOGGER'] = $app->share(
    function () use ($app) {
        return new DontThrowLoggerDecorator($app['monolog']);
    }
);

我在我的每项服务中都注入了
非破坏性日志记录程序,而不是独白日志记录程序。

为什么catch中存在\before
意外值异常
?错误表明无法打开日志文件,你确定这个错误不是由你的
writeln
语句引发的吗?@Olivier因为它试图捕捉
UnexpectedValueException
,而不是
myNamespace\UnexpectedValueException
@Darren什么是完整的堆栈跟踪,它说错误是在哪一行引发的?@deceze它正在引发异常行70。
$app['NOT_BREAKING_LOGGER'] = $app->share(
    function () use ($app) {
        return new DontThrowLoggerDecorator($app['monolog']);
    }
);