zoukankan      html  css  js  c++  java
  • php里面用魔术方法和匿名函数闭包函数动态的给类里面添加方法

    1.认识  __set  (在给不可访问属性赋值时,__set() 会被调用)

    也就是说你再访问一个类里面没有的属性,会出发这个方法

    class A{
        private  $aa = '11';
        public function __set($name, $value)
        {
            $this->$name = $value;
        }
    }
    $a = new A();
    $a->name = 'name';
    echo $a->name;

    2.认识 __set  (在对象中调用一个不可访问方法时,__call() 会被调用。)

    class B{
        private $bb = '22';
      public function __call($name, $arguments) { echo $name; var_dump($arguments); } } $b = new B(); $b->names();

    3.动态添加方法

    class B{
        private $bb = '22';
        public function __set($name, $value)
        {
            $this->$name = $value;
        }
        public function __call($name, $arguments)
        {//注意:没用形参$name
            return call_user_func($this->$name,$arguments);//通过这个把属性的匿名方法加进来 注意:$arguments 是一个数组
        }
    }
    $b = new B();
    $b->names = function(){echo 'this is a fun ';};
    $b->names();
    
    //这时候B类里面已经有一个 属性name 指向一个匿名方法
    //怎么运行呢? $b->name() 错误因为类里面没有这个方法 ---这个错误可以触发__call()魔术方法
    //这时候还不能在 匿名函数 中用B类里面的 属性

    4.动态加方法之,让闭包函数也能操作类里面的属性 参考(http://php.net/manual/zh/closure.bindto.php)

    class C{
        private $cc = '33';
        public function __set($name, $value)
        {
            //$this->$name = $value; //(和上面例子比较  就改动了这个)
            $this->$name = $value->bindTo($this,$this);//复制当前闭包函数,绑定指定的$this作用域对象,这样匿名函数就可以访问类的属性值了
        }
        public function __call($name, $arguments)
        {
            return call_user_func($this->$name,$arguments);
        }
    }
    $c = new C();
    $c->username = function ($strs){
        var_dump($strs);//这里其实是 call_user_func的$arguments传过来的是数组
        $this->cc=4;//可以操作作用于的属性值
        return '111';
    };
    echo $c->username('字符串');

    一个完整的例子:

    /**
     * 给类动态添加新方法
     *
     * @author fantasy
     */
    trait DynamicTrait {
        /**
         * 自动调用类中存在的方法
         */
        public function __call($name, $args) {
            if(is_callable($this->$name)){
                return call_user_func($this->$name, $args);
            }else{
                throw new RuntimeException("Method {$name} does not exist");
            }
        }
        /**
         * 添加方法
         */
        public function __set($name, $value) {
            $this->$name = is_callable($value)?
                $value->bindTo($this, $this):
                $value;
        }
    }
    /**
     * 只带属性不带方法动物类
     *
     * @author fantasy
     */
    class Animal {
        use DynamicTrait;
        private $dog = '汪汪队';
    }
    $animal = new Animal;
    // 往动物类实例中添加一个方法获取实例的私有属性$dog
    $animal->getdog = function() {
        return $this->dog;
    };
    echo $animal->getdog();//输出 汪汪队

    动态给类里面加方法,就是把一个闭包函数通过__set和__call结合call_user_func()等方法,加入进去,

    为了让匿名函数或闭包函数可以访问类的属性值,需要结合Closure类的Closure::bindTo (复制当前包对象,绑定到指定this作用域)

    参考:http://www.cnblogs.com/fps2tao/p/8727248.html

  • 相关阅读:
    前端/html5效果收藏
    Fiddler 网页采集抓包利器
    Es6 类class的关键 super、static、constructor、new.target
    js 倒计时毫秒级别显示
    雅虎34条军规
    javascript 异步请求封装成同步请求
    微信小程序 base64图片在canvas上画图
    chrome inspect 远程调试H5
    webpack 打包调试
    微信小程序云函数 添加数据到数据库
  • 原文地址:https://www.cnblogs.com/fps2tao/p/8728452.html
Copyright © 2011-2022 走看看