2011-04-21 29 views
10

有没有什么办法可以在PHP中为特定的命名空间设置错误处理程序?我正在构建一个小框架,我希望能够通过设置自定义错误处理程序并使用它抛出异常来尝试捕获其名称空间中的所有错误/警告/通知消息。 在特定命名空间之外触发的错误应该以常规方式运行。限制PHP的错误处理程序到特定的命名空间(s)

可以用PHP来完成吗?

谢谢。

+2

我不这么认为:没有关于'debug_backtrace()'返回数据中名称空间的信息(根据这个信息你可以告诉你的错误处理程序如何反应)。有兴趣看看是否有任何事情发生。 – 2011-04-21 19:32:21

回答

2

道歉提前发布前没有真正尝试了这一点:

的PHP传递给你的错误处理方法(和它通常被忽略)是一个数组$ errcontext指向第五个参数(可选)当前的PHP符号表。我的想法是,如果您可以从Rudie提出的异常的回溯中提取名称空间,那么也可以使用与$ errcontext类似的方式提取名称空间信息。如果这是真的,那么你的错误处理程序可以检查自己的命名空间,如果当前命名空间与错误处理程序设计的命名空间不匹配,则通过返回false来检查自己的命名空间。另外,错误处理程序可以是“堆栈”,这意味着至少在原则上(如果我的建议是“我的”$ errcontext实际工作),您可以为每个名称空间设置单独的错误处理程序。

我并不是说这种方法比Josh和Rudie提出的解决方案更“优雅”,但它看起来与你想要做的是一致的 - 这是强加一种对您的错误处理程序的作用域限制。

祝你好运!

+0

谢谢,这真的很有帮助。 $ errcontext并不是我所希望的,但我有一些很好的想法。我将在一个对象中定义错误处理程序,该对象有一堆存储在静态数组中的回调函数名称(因为set_error_handler只是覆盖了以前定义的函数)。然后我为每个函数使用call_user_func并检查返回的值。在这些函数中,我将使用由Rudie和Josh的答案组合而成的想法。实际上,没有本地实现(我意识到)堆栈错误处理程序是令人遗憾的。这是丑陋的,昂贵的...它的工作原理。 – Mikk 2011-05-03 23:19:03

+0

实际上,set_error_handler()*不会覆盖以前声明的错误处理程序 - 它会将新的错误处理程序推送到“堆栈”上,并且PHP解释程序在处理错误时首先调用它。如果新的错误处理程序退出,那么堆栈中的其余错误处理程序都不会被调用(所以就好像放弃了它们一样),但是如果错误处理程序返回值false,则会调用堆栈中的下一个错误处理程序。海事组织会让PHP处理你的“堆栈回调函数”比将它们自己加载到数组中更清洁,但当然这可以工作。 – Peter 2011-05-04 14:19:20

0

可以用PHP来完成吗?

它可以很容易地完成我会说。而不实际编写代码,这是我会怎么做:

  1. 创建try/catch块
  2. 捕获所有异常(\Exception
  3. 找到最后一个叫做类(在$exception->getTrace()某处)
  4. 那类将有其命名空间,它的名字:some\name\space\Class
  5. 使用dirname($namespace)(在这种情况下"Class")删除类名
  6. 做w^hatever你,结果好像还是重新抛出异常:throw $exception;

编辑
甚至倒闭具有命名空间:

namespace oele\boele; 

$fn = function() { 
    throw new \Exception; 
}; 

try { 
    $fn(); 
} 
catch (\Exception $ex) { 
    print_r($ex); 
} 

$ex->getTrace()[0]['function']oele\boele\{closure}

编辑
太糟糕trace阵列没有每个元素都没有钥匙'namespace'

+0

我想操作系统询问'set_error_handler()',因为不需要将所有东西都包装在巨大的try/catch块中 – knittl 2011-04-21 19:37:55

+0

如果它是一个框架,它的大部分'应该'被封装在FrontController的一个大的try/catch块无论如何...国际海事组织 – Rudie 2011-04-21 19:39:48

+0

是的,我想的是set_error_handler()函数。捕捉你自己的自定义异常不应该是问题idneed。 – Mikk 2011-04-21 20:40:55

1

我还没有尝试过,所以我提前道歉之前,要做到这一点,如果这不工作(至少是它可以让你思考),但是这是我怎么会尽力做到这一点:

由于你的命名空间将会是一个整体更大的框架的一部分,我会让框架中的所有类扩展一个基类(为此可以称之为BaseClass)。在那个类中,我会创建一个名为errorHandler()的方法。在这个函数内部,你可以为你的异常处理做任何你想做的事情(甚至可以自己抛出一个异常)。

既然你有这个功能,我们必须弄清楚如何获得这个函数。由于名称空间中的所有对象都扩展了BaseClass,因此它们都可以访问此errorHandler()方法。现在在你的代码中,你可以使用正常的try/catch块来捕获发生的异常,而不是使用标准的异常模型,而是调用$ this-> errorHander()(现在我想到了它,你可能想把这里的一些参数 - 可能是你从catch语句中得到的异常)。这应该会为您提供所需的代码中预期会出现问题的部分。

我们需要弄清楚的下一部分是处理您不期望的异常,以及您计划如何通过此错误处理程序来路由这些异常。这个更棘手一些,因为这个解决方案依赖于某个try/catch块。由于这是一个框架,我将假定所有事情都是通过index.php或其他引导文件(如Zend Framework之类的东西)运行的。如果是这种情况,那么我会把你的try/catch放在框架开始执行的任何地方。根据您在catch块中得到的异常,您可以决定是否要通过errorHandler()方法运行它。我必须管理这个部分不知何故感觉有点肮脏,应该有一个更好的方式来做到这一点(也许一旦你得到更好的解决方案会出现本身)。

希望这可以帮助你在你的过程中走得更远。如果有人有一个想法如何让最后一部分不觉得太脏,这将是伟大的。