我们都同意,为不同的任务使用不同的异常类型是可行的方法。
但是,我们最终会创建像这样的鬼文件:
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Dojo
* @subpackage View
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Dojo_Exception
*/
require_once 'Zend/Dojo/Exception.php';
/**
* @category Zend
* @package Zend_Dojo
* @subpackage View
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Dojo_View_Exception extends Zend_Dojo_Exception
{
}
然后Zend_Dojo_Exception
和Zend_Exception
...
这个问题有没有通用方法?
像throw new \My\Just\Declared\Exception\ (which extends \My\Just\Exception)
之类的东西,所以我没有必须包装并要求所有这些鬼文件?
答案 0 :(得分:7)
您似乎专注于这些“鬼”类的想法 - 没有实现的类或标记接口。坦白说,你错过了这一点。
在ZF1中,Exception类只是组件级别,该级别的所有异常都接收相同的异常类。这实际上只允许以下类型的捕获:
这比在任何地方简单地抛出“例外”要好一点;你需要仔细检查异常消息,以了解出了什么问题。
现在,请仔细阅读提案。
提案的目的是在捕获异常时允许更多级别的粒度:
基本上,我们现在只允许在 TYPE 异常上提供更大的粒度;如果您尝试的操作可能抛出多个相同类型的异常,则只需要检查消息。通常,情况并非如此。
SPL异常在语义上相当丰富,并且ZF中的许多异常将更好地归类为这些类型(例如,无效参数应该引发InvalidArgumentException;无法解析插件将是一个很好的RuntimeException;等等)。使用ZF1,这是不可能的 - 我们必须继承组件级异常,句点。通过移动到标记接口,我们既可以捕获组件级异常以及SPL级别,也可以获得更具体的异常类型。
答案 1 :(得分:1)
有些人使用autoloader即时创建例外。
答案 2 :(得分:1)
在良好实践中,并非真的...如果你真的想要这样做,你可以做一些黑客攻击,但我仍然认为它们更邪恶。
例如,其中一个黑客是eval
这些类通过自动加载器存在。这很糟糕,因为如果有人grep
用于例外的定义或者你的软件包抛出的异常,那么它们将会是一大堆nada的回报......
public static function load($name) {
$parts = explode('_', $name);
if (strtolower(end($parts)) == 'exception') {
//make it extend the proper exception
array_pop($parts); //get rid of the last Exception bit
array_pop($parts);
$parts[] = 'Exception';
$parent = implode('_', $parts);
$code = 'class '.$name.' extends '.$parent . '{}';
eval($code);
}
}
但是,请允许我强调这通常是一个坏主意。
就个人而言,我从多个“基本例外”(通常是SPL
exceptions)继承。因此,例如Database_Connection_Exception
可能会扩展RuntimeException
,尝试提交非开放事务可能会抛出Database_Not_In_Transaction_Exception
,这可能会扩展LogicException
。关键是单独声明它们可以让你做的不仅仅是直接的heiarchal继承(更不用说文档更好了,因为人们可以看一眼定义的异常,你可以实际覆盖方法以更好地满足你的需求,如果合适的话)...
修改:根据您提到Zend
每个子包执行一个例外的倾向,我就是这样做的...
基本上,我在整个应用程序中使用了一些“全局”异常。这些包括(但不限于):ClassNotFoundException
,FileNotFoundException
,NotCallableException
和其他一些。基本上只是那些不是特定于包的,但需要传达比核心PHP异常更多的含义......
然后,我只在包级别声明异常。在该目录(package/exceptions
)中,我根据需要声明了每个例外。因此,一个子包可能有5或10个例外来区分不同的条件,而另一个子包(在同一个包中)可能没有。所以我根据需要声明它们,以便异常意味着发生了什么。
我这样做的原因很简单。我不关心where
异常被抛出(如果我真的这样做,我可以检查在异常内部自动生成的回溯)。我关心why
异常被抛出。这让我能够正确处理异常......
答案 3 :(得分:0)
从我的观点来看,异常是或者应该只在开发模式中可见。生产模式不应显示用户/客户端的异常,而是显示“遇到问题”或类似内容的简单页面。应该记录这些例外情况。最重要的是,它们主要用于调试或在必要时控制执行流程(当它们是预期的时候)。您可以简单地抛出Zend_Exception
,但这只会使您的异常过于通用,并且很难在try..catch中找到原因
我通常创建 ghost文件 - 就像你调用它们一样 - 主要是在“包”级别上,或者当一个方法被抛出异常时(所以我可以抓住它)例外并因此对待它。)
您最终可能会得到许多 ghost文件,但这样只会使您的项目更有条理,最终也很容易调试。由于这些例外仅在需要的基础上加载,因此拥有大量例外不会影响性能。
答案 4 :(得分:0)
事实上,PHP已经有异常子类,有关完整列表,请参阅here。因此,关于其使用的文档非常有限,您可以查看this post on php exceptions以获取每个文档的含义。