Помимо прочего, я расширил класс исключений, добавив метод 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 ...
}
}