Cast the current object ($this) to a descendent class

后端 未结 5 685
刺人心
刺人心 2020-11-29 11:08

I have a class where it may be necessary to change the object to a descendent class further down the line. Is this possible? I know that one option is to return a copy of it

5条回答
  •  眼角桃花
    2020-11-29 11:20

    For simple classes this may work (I am using this successfully in some rare cases):

    function castAs($sourceObject, $newClass)
    {
        $castedObject                    = new $newClass();
        $reflectedSourceObject           = new \ReflectionClass($sourceObject);
        $reflectedSourceObjectProperties = $reflectedSourceObject->getProperties();
    
        foreach ($reflectedSourceObjectProperties as $reflectedSourceObjectProperty) {
            $propertyName = $reflectedSourceObjectProperty->getName();
    
            $reflectedSourceObjectProperty->setAccessible(true);
    
            $castedObject->$propertyName = $reflectedSourceObjectProperty->getValue($sourceObject);
        }
    }
    

    Usage in my case:

    $indentFormMapper = castAs($formMapper, IndentedFormMapper::class);
    

    More abstract:

    $castedObject = castAs($sourceObject, TargetClass::class);
    

    Of course TargetClass has to inherit from the class of sourceObject and you have to make all protected and private properties public in TargetClass to get this work.

    I use this to change FormMapper (https://github.com/sonata-project/SonataAdminBundle/blob/3.x/src/Form/FormMapper.php) on the fly to IndentedFormMapper by adding a new method called chain:

    class IndentedFormMapper extends FormMapper
    {
        /**
         * @var AdminInterface
         */
        public $admin;
    
        /**
         * @var BuilderInterface
         */
        public $builder;
    
        /**
         * @var FormBuilderInterface
         */
        public $formBuilder;
    
        /**
         * @var string|null
         */
        public $currentGroup;
    
        /**
         * @var string|null
         */
        public $currentTab;
    
        /**
         * @var bool|null
         */
        public $apply;
    
        public function __construct()
        {
        }
    
        /**
         * @param $callback
         * @return $this
         */
        public function chain($callback)
        {
            $callback($this);
    
            return $this;
        }
    }
    

提交回复
热议问题