PHP:在运行时将自定义方法添加到 a(n 内部)类(派生自异常类)


PHP: add a custom method to a(n internal) class (derived from exception class) at runtime

我扩展了异常类以添加方法getMessageHTML((。在我的应用程序中,我想捕获任何异常 - 以及派生内部类的异常,例如 ReflectionException - 并希望能够在任何异常和任何派生异常上使用 getMessageHTML(( 方法或其他自定义方法。

有没有办法在运行时将方法或特征添加到内部类(如异常类或 ReflectionException 类(中?

我想到的唯一解决方案是将任何捕获的异常包装到我的扩展异常类中,例如:

$anyException = new Exception(); //or ReflectionException, or ...
$wrappedException = MyException::wrap($anyException);
$wrappedException->getMessageHTML(); //or any other custom method

是否有任何实现,允许将方法引入每个派生的内部或外部类/对象,以便任何对象都知道它?

$anyException = new Exception(); //or ReflectionException, or ...
$anyException->getMessageHTML();

然后我可以简单地做:

try
{
    throw <anyException>(); //like throw Exception() or throw ReflectionException() ...
}
catch($e)
{
    $e->getMessageHTML(); //its assured that the method is known.
}

现在我是这样做的:

class MyException extends Exception
{
    protected static function cast($destination, $sourceObject)
    {
        if(is_string($destination))
            $destination = new $destination();
        $sourceReflection = new 'ReflectionObject($sourceObject);
        $destinationReflection = new 'ReflectionObject($destination);
        $sourceProperties = $sourceReflection->getProperties();
        foreach($sourceProperties as $sourceProperty)
        {
            $sourceProperty->setAccessible(true);
            $name = $sourceProperty->getName();
            $value = $sourceProperty->getValue($sourceObject);
            if ($destinationReflection->hasProperty($name))
            {
                $propDest = $destinationReflection->getProperty($name);
                $propDest->setAccessible(true);
                $propDest->setValue($destination,$value);
            }
            else
                $destination->$name = $value;
        }
        return $destination;
    }
    public static function wrap(Exception $exception)
    {
        $wrap = $exception;
        if(!$exception instanceof MyException)
            $wrap = self::cast(__CLASS__, $exception);
        return $wrap;
    }
    public function getMessageHTML()
    {
        //some code ...
    }
}
try
{
    throw new ReflectionException('test');
}
catch(Exception $e)
{
    $e = MyException::wrap($e);
    echo $e->getMessageHTML();
}
或 -

更简单 - 并且具有具有前一个例外可用的优点:

class MyException extends Exception
{
    public static function wrap(Exception $exception)
    {
        $wrap = $exception;
        if(!$exception instanceof AppException)
        {
            try
            {
                throw new AppException($exception->getMessage(), $exception->getCode(), $exception);
            }
            catch(AppException $e)
            {
                $wrap = $e;
            }
        }
        return $wrap;
    }
    public function getMessageHTML()
    {
        //some code ...
    }
}