Is it possible to use mixins in php

前端 未结 5 2048
猫巷女王i
猫巷女王i 2020-12-08 19:33

I came to know about mixins.So my doubt is, is it possible to use mixins in php?If yes then how?

5条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-08 20:22

    I based mixins functionality on the blog entry found at jansch.nl.

    class Node
    {
        protected $__decorator_lookup = array();
    
        public function __construct($classes = array())
        {              
            foreach($classes as $class)
            if (class_exists($class))
            {
                $decorator = new $class($this);
                $methods = get_class_methods($decorator);
                if (is_array($methods))
                    foreach($methods as $method) 
                        $this->__decorator_lookup[strtolower($method)] = $decorator;
            }
            else
                trigger_error("Tried to inherit non-existant class", E_USER_ERROR);
        }
    
        public function __get($name)
        {
            switch($name)
            {
                 default:
                    if ($this->__decorator_lookup[strtolower($name)])
                        return $this->__call($name);
            }
        }
    
        public function __call($method, $args = array()) 
        {
            if(isset($this->__decorator_lookup[strtolower($method)]))
                return call_user_func_array(array($this->__decorator_lookup[strtolower($method)], $method), $args);
            else
                trigger_error("Call to undefined method " . get_class($this) . "::$method()", E_USER_ERROR);
        }
    
        public function __clone()
        {
            $temp = $this->decorators;
            $this->decorators = array();
    
            foreach($temp as $decorator)
            {
                $new = clone($decorator);
                $new->__self = $this;
                $this->decorators[] = $new;
            }
        }
    }
    
    class Decorator
    {
        public $__self;
    
        public function __construct($__self)
        {
            $this->__self = $__self;
        }
    
        public function &__get($key)
        {
            return $this->__self->$key;
        }
    
        public function __call($method, $arguments)
        {
            return call_user_func_array(array($this->__self, $method), $arguments);
        }
    
        public function __set($key, $value)
        {
            $this->__self->$key = $value;
        }
    }
    
    class Pretty extends Decorator
    {
        public function A()
        {
            echo "a";
        }
    
        public function B()
        {
            $this->b = "b";
        }
    }
    
    $a = new Node(array("Pretty"));
    
    $a->A(); // outputs "a"
    $a->B();
    
    echo($a->b); // outputs "b"
    

    EDIT:

    1. As PHP clone is shallow, added __clone support.
    2. Also, bear in mind that unset WON'T work (or at least I've not managed to make it work) within the mixin. So - doing something like unset($this->__self->someValue); won't unset the value on Node. Don't know why, as in theory it should work. Funny enough unset($this->__self->someValue); var_dump(isset($this->__self->someValue)); will produce correctly false, however accessing the value from Node scope (as Node->someValue) will still produce true. There's some strange voodoo there.

提交回复
热议问题