1

I extended the exception class amongst other things to add a method getMessageHTML(). In my application I want to catch any exception - also exceptions of derived internal classes like e.g. the ReflectionException - and want to be able to use a getMessageHTML() method or other custom methods on any exception and any derived exception.

Is there any way, to add a method or trait to an internal class like the exception class or the ReflectionException class at runtime?

The only solution that comes to my mind is to wrap any catched exception into my extended exception class like:

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

is there any implementation, that allows to introduce a method to every derived internal or foreign class/object, so that any object knows it?

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

then i could simply do:

try
{
    throw <anyException>(); //like throw Exception() or throw ReflectionException() ...
}
catch($e)
{
    $e->getMessageHTML(); //its assured that the method is known.
}
georg
  • 211,518
  • 52
  • 313
  • 390
lsblsb
  • 1,292
  • 12
  • 19
  • PHP classes are sealed and the support of monkey patching [is quite poor](http://stackoverflow.com/questions/137006/redefine-class-methods-or-class). So I'm afraid the answer is "no way". – georg Dec 16 '14 at 12:56
  • What would the implementation of getMessageHtml() look like? Is it not possible to create an ExceptionView of sorts that takes the exception as parameter and the logic to convert to HTML happens in your view? – qrazi Dec 16 '14 at 13:05
  • thanks for your reply so far. the view idea would be similar to the idea of using a wrapper method - in this case the wrapper method does the view-thing. – lsblsb Dec 16 '14 at 13:27

2 Answers2

0

For now I am doing it like this:

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();
}
lsblsb
  • 1,292
  • 12
  • 19
0

or - simpler - and with the advantage to have the previous exception available:

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 ...
    }
}
lsblsb
  • 1,292
  • 12
  • 19