PHP的try-catch错误报告

3
我有一个应用程序,它依赖于一个SOAP服务器来生成内容。此外,对站点的身份验证基于单独的LDAP服务器。显然,如果其中任何一个出现问题或无响应,则站点将出现故障。
我正在尝试设计一种方案,以便为站点管理员提供错误报告,并在站点崩溃时向用户提供良好的提示信息。错误报告实际上只是一个电子邮件、数据库插入或PHP $_COOKIE、$_SERVER、$_SESSION、$_REQUEST以及可能的SoapFault异常的服务器文本文件日志记录。如果发生任何潜在的站点问题,这些信息将帮助我进行调试。
目前,我的站点设计如下:
SoapClientInterface (defines soap functionality)
      / \
       |
       |   implements
       |
Client (the client implementing the interface, try/catch blocks on all soap calls here) 
      / \
       |
       |  extends
       |
 Authorization (asserts soap objects returned from server/ requests going to server 
               are appropriate for the user performing the request) 
      / \
       |
       | extends
       | 
  {all children classes using the soap interface defined on this level} 

从上面的糟糕图表 :-) 我有一个类客户端,它包含了所有的try catch块用于soapfault异常,并想知道在catchs中做两件事的最佳方法: 1. 通知用户操作失败(我所有的功能都在if / else块中,如果我确定操作失败,我会将用户重定向到状态页面并告诉他们他们的操作失败了。 2. 报告情况以进行调试(目前此功能是在状态页面中定义的简单函数,当状态页面获取错误代码时,我们会转储Cookier、Server、Session和Request变量,并将其发送电子邮件给站点管理员。
任何关于此的建议都将不胜感激,或者如果您需要澄清,请询问。
编辑:根据我的网页编程经验,我的应用程序通常会在执行操作的页面上显示用户操作的状态,而不会重定向到其他地方。这是我第一次编写应用程序,对于所有状态消息,都执行用户操作并重定向到单独的页面。我是否应该为自己做法感到遗憾?是否有人认为在具有单个状态页面的所有站点操作或具有报告页面上的类/函数的设计方面存在优点?(我正在考虑状态页面本身的设计以及如何报告错误等。)
1个回答

1

个人认为这取决于错误类型。根据我的经验,有三种异常类型:可以忽略的异常、可以解决的异常和需要终止执行的异常(如果你只是想删除文件,则可以忽略file_not_found异常;如果资源有替代来源,则可能可以解决resource_not_available异常;如果出现database_connection_failure异常,则需要终止应用程序,除非你有备份)...捕获的异常类型将决定你如何处理它。

个人安装了一个全局异常处理程序...然后,在我的catch块中,我可以选择清理请求、以不同方式处理请求、继续执行(如果是可恢复的异常),或者重新抛出异常(查询错误等)。如果异常到达堆栈的顶部(全局处理程序),那么我会记录错误(我使用数据库表来记录)并抛出500内部服务器错误。

就错误重定向而言,我无法忍受。如果错误是暂时性的,那么为什么我不能只刷新页面呢?为什么我必须返回(如果我能的话)再试一次...

只要正确输出缓冲区,你几乎总能够在不向用户显示任何敏感信息的情况下呈现错误页面(我说几乎,因为对于致命错误你无法呈现任何内容)...否则你会违反HTTP规范(因为你正在说当前页面发生错误而不是正确的“发生错误”的状态头的临时重定向)...


@ircmaxell,首先感谢您的周到评论,非常感谢。其次,例如在发生soapfault异常的情况下,如果用户尝试执行更新操作,您建议只向用户报告出现了错误,让他们留在表单上并可能尝试重新提交吗? - Chris
@ircmaxell 那么我只需要定义自己的函数来处理我想要的所有内容,就可以使用set_exception_handler()了吗?在这个自定义异常处理程序中定义错误报告、必要时进行重定向等等?然后只需要让我的Client类抛出异常即可?我还不完全理解如何以最佳方式将自定义处理程序纳入我的设计中。 - Chris
嗯,是的和不是的。除非问题出在他们的输入上,否则我不会将它们留在表单上。我会将它们留在URL上,并将状态头设置为“500”,并显示一个页面,上面写着“由于意外的服务器错误,您的请求无法处理。请稍后再试。如果此错误仍然存在,请联系blah...”假设您没有紧密的CSRF保护(这意味着在提交时删除csrf令牌的会话密钥),他们可以刷新页面以重试。重定向的问题在于,他们不知道错误发生在哪里... - ircmaxell
exception_handler是一个函数,如果没有任何地方“捕获”异常(它会一直冒泡到栈的顶部),就会被调用。基本上,当PHP通常对未处理的异常致命错误时,它会调用set_exception_handler中指定的回调函数。这样,您可以在那里进行所有的日志记录和错误页面的生成。这避免了为了避免“未处理异常”致命错误而将所有内容包装在一个巨大的try/catch块中的情况。 - ircmaxell
可以使用类::函数而不是仅仅使用函数吗?这并非必须,只是我自己很好奇,在谷歌上搜索并没有找到任何关于能否这样做的信息。例如:set_exception_handler(ErroClass::staticFunction)。 - Chris
当然可以。它接受标准回调函数,因此您可以使用array($foo, 'bar')来调用实例方法,或者使用array('Foo', 'bar')来调用静态方法...(我尽量避免使用Class::method回调语法)。您甚至可以使用匿名函数。 - ircmaxell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接