第二组是逻辑(logic )组。这组由DomainException、InvalidArgumentException、LengthException、OutOfRangeException组成。这些异常也是LogicException的子类,当然也是PHP的Exception的子类。在有状态不定,或者错误的方法/函数的参数时使用这些异常。为了更好地理解这一点,我们先看看最后一组异常
最后一组是运行时(runtime )组。它由OutOfBoundsException、OverflowException、RangeException、UnderflowException、UnexpectedValueExceptio组成。这些异常也是RuntimeException的子类,当然也是PHP的Exception的子类。在“运行时”(runtime)的函数、方法发生异常时,这些异常(运行时组)会被调用
逻辑组和运行时组如何一起工作?如果你看看对象的剖析,通常是发生的是两者之一。首先,对象将跟踪并改变状态。这意味着对象通常是不做任何事情。它可能会传递结构给��,它可能会通过setter和getter设置一些东西(译者注:例如$this->foo='foo'),或者,它可能会引用其他对象。第二,当对象不跟踪或改变状态,这代表正在操作——做它该做的事。这是对象的运行时(runtime)。例如,在对象的一生中,它可能被创建,设置一些东西,那么它可能会被setFoo($foo),setBar($bar)。在这些时候,任何类型的LogicException应该被提高。此外,当对象内的方法被带参数调用时,例如$object->doSomething($someVariation);在前几行检查$someVariation变量时,可能抛出一个LogicException。完成检查$someVariation后,它继续做它该做的doSomething(),这时被认为是它的“运行时”(runtime),在这段代码中,可能抛出RuntimeExcpetions异常。
要理解得更好,我们来看看这个概念在代码中的运用:
class Foo
{
protected $number = 0;
protected $bar = null;
public function __construct($options)
{
/** 本方法抛出LogicException异常 **/
}
public function setNumber($number)
{
/** 本方法抛出LogicException异常 **/
}
public function setBar(Bar $bar)
{
/** 本方法抛出LogicException异常 **/
}
public function doSomething($differentNumber)
{
if ($differentNumber != $expectedCondition) {
/** 在这里,抛出LogicException异常 **/
}
/**
* 在这里,本方法抛出RuntimeException异常
*/
}
}
现在理解了这一概念,那么,对代码库的使用者来说,这是做什么的呢?使用者可以随时确定对象的异常状态,他们可以用异常的具体的类型来捕获(catch)异常,例如InvalidArgumentException或LengthException,至少也是LogicException。通过这种级别的精度调整,和类型的多样,他们可以用LogicException捕获最小的异常,但也可以通过实际的异常类型获得更好的理解。同样的概念也适用于运行时的异常,可以抛出更多的特定类型的异常,并且不论是特定或非特定类型的异常,都可以被捕获(catch)。它可以给使用者提供更详细的情况和精确度。
下面是一个关于SPL异常的表,您可能会有兴趣
类库代码中的最佳实践
PHP 5.3 带来了新的异常类型, 同时也带给我们新的最佳实践. 除了将某些特定的异常(如: InvalidArgumentException, RuntimeException)标准化外, 捕捉组件级的异常, 也很重要. 关于这方面, ZF2 wiki 和 PEAR2 wiki 上面有深入的探讨.
简而言之, 除了上面提到的各种最佳实践, 我们还应该用 Marker Interface 来创建一个组件级的异常基类. 通过创建组件级的 Marker Interface, 用在组件内部的异常既能继承 SPL 的异常类型, 也能在运行时被各种代码捕捉. 我们来看下列代码:
// usage of bracket syntax for brevity
namespace MyCompany\Component {
interface Exception
{}
class UnexpectedValueException
extends \UnexpectedValueException
implements Exception
{}
class Component
{
public static function doSomething()
{
if ($somethingExceptionalHappens) {
throw new UnexpectedValueException('Something bad happened');
}
}
}
}