Я не знаю, возможно ли обмануть оператор instanceof
так, как вы хотите (узнайте класс как подкласс, если это не так), но я думаю, что нашел решение, которое может удовлетворить ваши потребности.Если я правильно понимаю вашу проблему, то вы просто хотите внедрить некоторые методы в любой класс с минимальными изменениями во всем коде.
Я думаю, что лучший способ подготовить решение в этом случае - использовать черты (описано * 1004).* здесь ).С помощью признаков вы можете добавлять методы в любой класс без прямого наследования, и он может перезаписывать методы из базового класса.Для перезаписи метода с чертами вам, конечно, нужны подклассы, но они могут быть созданы динамически.Я ничего не знаю о вашем процессе упаковки, но в своем решении я использовал специальный класс для него.Давайте посмотрим на мое решение:
namespace someNameSpace;
//this is one of your class that you want to wrap - it can be declare under some other namespace if you need
class yourBaseClass { }
//your wrapper class as a trait
trait yourWrapper { }
//class for wrapping any object
class ObjectWrapperClass
{
//method for change object class (described on http://stackoverflow.com/a/3243949/4662836)
protected static function objectToObject($instance, $className)
{
return unserialize(sprintf('O:%d:"%s"%s', strlen($className), $className, strstr(strstr(serialize($instance), '"'), ':')));
}
//wrapping method
//$object is a object to be wrapped
//$wrapper is a full name of the wrapper trait
public static function wrap($object, $wrapper)
{
//take some information about the object to be wrapped
$reflection = new \ReflectionClass($object);
$baseClass = $reflection->getShortName();
$namespace = $reflection->getNamespaceName();
//perpare the name of the new wrapped class
$newClassName = "{$baseClass}Wrapped";
//if new wrapped class has not been declared before we need to do it now
if (!class_exists($newClassName)) {
//prepare a code of the wrapping class that inject trait
$newClassCode = "namespace {$namespace} { class {$newClassName} extends {$baseClass} { use {$wrapper}; } }";
//run the prepared code
eval($newClassCode);
}
//change the object class and return it
return self::objectToObject($object, $namespace . '\\' . $newClassName);
}
}
//lets test this solution
$originalObject = new yourBaseClass();
$wrappedObject = ObjectWrapperClass::wrap($originalObject, 'yourWrapper');
if ($wrappedObject instanceof yourBaseClass) {
echo 'It is working';
}
Как вы можете видеть, что все происходит в процессе переноса.
Если у вас есть больше упаковщиков, тогда вы можете подготовить новое имя класса с переносом другим способом (например, должен быть связан с именем оболочки).