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

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

  1. class A{
  2. private $aa = '11';
  3. public function __set($name, $value)
  4. {
  5. $this->$name = $value;
  6. }
  7. }
  8. $a = new A();
  9. $a->name = 'name';
  10. echo $a->name;

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

  1. class B{
  2. private $bb = '22';
      public function __call($name, $arguments)
  3. {
  4. echo $name;
  5. var_dump($arguments);
  6. }
  7. }
  8. $b = new B();
  9. $b->names();

3.动态添加方法

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

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

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

一个完整的例子:

  1. /**
  2. * 给类动态添加新方法
  3. *
  4. * @author fantasy
  5. */
  6. trait DynamicTrait {
  7. /**
  8. * 自动调用类中存在的方法
  9. */
  10. public function __call($name, $args) {
  11. if(is_callable($this->$name)){
  12. return call_user_func($this->$name, $args);
  13. }else{
  14. throw new \RuntimeException("Method {$name} does not exist");
  15. }
  16. }
  17. /**
  18. * 添加方法
  19. */
  20. public function __set($name, $value) {
  21. $this->$name = is_callable($value)?
  22. $value->bindTo($this, $this):
  23. $value;
  24. }
  25. }
  26. /**
  27. * 只带属性不带方法动物类
  28. *
  29. * @author fantasy
  30. */
  31. class Animal {
  32. use DynamicTrait;
  33. private $dog = '汪汪队';
  34. }
  35. $animal = new Animal;
  36. // 往动物类实例中添加一个方法获取实例的私有属性$dog
  37. $animal->getdog = function() {
  38. return $this->dog;
  39. };
  40. echo $animal->getdog();//输出 汪汪队

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

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

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

php里面用魔术方法和匿名函数闭包函数动态的给类里面添加方法的更多相关文章

  1. 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数

    [源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...

  2. python 函数--闭包函数

    一.闭包函数: 在一个外函数中定义一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用. 二.实例: def outer(a): #外函数 b = 10 #临时变量 def i ...

  3. PHP函数(六)-匿名函数(闭包函数)

    匿名函数能够临时创建一个没有名称的函数,常用作回调函数参数的值 <?php $test = function($a){ echo "Hello,".$a; }; $test( ...

  4. python 内嵌函数, 闭包, 函数装饰器

    一.  函数内嵌 闭包 在python中,函数可以作为返回值, 可以给变量赋值. 在python中, 内置函数必须被显示的调用, 否则不会执行. #!/usr/bin/env python #-*- ...

  5. ios开发runtime学习三:动态添加方法(实际应用少,面试)

    #import "ViewController.h" #import "Person.h" /* 1: Runtime(动态添加方法):OC都是懒加载机制,只要 ...

  6. 如何为jquery添加方法

    以下内容引自一位网友的帖子: jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery ...

  7. 快速上手Runtime(四)之动态添加方法

    如果一个类方法非常多,加载类到内存的时候也比较耗费资源,可以使用动态给某个类,添加方法解决.做到优化内存,节省资源的效果. // // Person.m // ResolveInstanceMetho ...

  8. JavaScript匿名自执行函数~function(){}

    原博客:https://blog.csdn.net/yaojxing/article/details/72784774 1.匿名函数的常见场景 js中的匿名函数是一种很常见的函数类型,比较常见的场景: ...

  9. php的匿名函数和闭包函数

    php的匿名函数和闭包函数 tags: 匿名函数 闭包函数 php闭包函数 php匿名函数 function use 引言:匿名函数和闭包函数都不是特别高深的知识,但是很多刚入门的朋友却总是很困惑,因 ...

随机推荐

  1. Netty源码学习(七)FastThreadLocal

    0. FastThreadLocal简介 如同注释中所说:A special variant of ThreadLocal that yields higher access performance ...

  2. (10)java基础知识-字符串

    String s和 new String 的区别 String s1="hello"; String s2= new String("hello"); Stri ...

  3. 中矿大新生赛 A 求解位数和【字符串】

    时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 给出一个数x,求x的所有位数的和. 输入描述: 第 ...

  4. [COCI2015]ZMIJA

    题目大意: 一个$n\times m(n,m\leq1000)$的格子中有若干金币,从左下角出发,每一步可以进行如下操作: 1.向当前方向前进一格: 2.向上移动一步,并调转当前方向. 一开始的方向是 ...

  5. Struts2笔记--文件下载

    Struts2提供了stream结果类型,该结果类型是专门用于支持文件下载功能的.配置stream类型的结果需要指定以下4个属性. contentType:指定被下载文件的文件类型 inputName ...

  6. SQL Server 2017 EXPRESS 安装 SQLCMD 设置远程连接

    1.配置管理器内启动TCP/IP协议(端口改为1433)以及加入防火墙允许 2.进入本地实例: cmd Microsoft Windows [版本 ] (c) Microsoft Corporatio ...

  7. Features (OCMock 2)

    This page describes the features present in OCMock 2.x, using the traditional syntax. All these feat ...

  8. codeforces559A--Gerald&#39;s Hexagon(计算几何)

    A. Gerald's Hexagon time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. python软件工程知识

    软件工程知识 3.1 程序设计过程中,常用伪代码来"思考"一个程序,在将伪代码程序转换成python程序. 3.2 所有python程序都可以给予6类控制结构来创建(顺序,if, ...

  10. gamma校正原理

    http://blog.csdn.net/u013286409/article/details/50239377 目录(?)[-]   图2中左图为原图,中图为gamma = 1/2.2在校正结果,原 ...