php Closure::bind的参数说明
publicstatic Closure Closure::bind ( Closure $closure , object$newthis [, mixed$newscope = 'static' ] )
一、函数意义:
对于 Closure::bind PHP官方文档的解释是:“Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。”
闭包:即匿名函数,匿名函数的另一种叫法。所以前半句的意思,就是“复制一个匿名函数”。
后半句话,就比较拗口了,“绑定指定的$this对象和类的作用域”。我的理解是:“$this对象”直接理解为“被new()创建的对象”;“类的作用域”即定义类的大括号中间的全部内容。
至于“绑定”,意思就是,匿名函数在执行时,函数内部的$this(如果函数内部有[$this->成员名]的这种用法的话)是被绑定的,绑定的对象就是参数二的 $newthis;当然,$this肯定是用来被绑定类的实例的,如果想访问类的静态成员的话,就因该用 【类名::成员名】或者【static::成员名】或者【self::成员名】。
所有,Closure::bind()是匿名函数在处理时,用来绑定类的对象和作用域的(我觉得说成“或”应该更准确一些,现在不用细究,后面会讲到),所以如果你只是单纯的用匿名函数但是却不需要绑定类对象或者制定这个匿名函数的类的作用域的话,就不需要用Closure::bind()方法了。
二、参数说明和用法:
2.1 第一个参数$closure,其实就是一个匿名函数,之所以参数类型是Closure,这是因为“匿名函数目前是通过 Closure 类来实现的”。
2.2 第二个参数$newthis,如果匿名函数需要用到类实例的话,就必须传一个类的实例;如果不需要的话,这个参数直接传“null”就可以。
2.3 第三个参数$newscope,scope的中文意思为“范围,作用域”。如果不指定这个参数,那么默认,在匿名函数内部,只能使用通过$newthis这个参数传入进来的对象的pulic成员;而如果指定了这个参数的话,那么就可访问这个参数所表示的类的作用域内部的所有成员,包括private和protected。
三、举个栗子:
class T { private static $name = '我是T里面的私有属性 $name <br>'; private function show() { echo "我是T里面的私有函数:show <br>"; } protected function who() { echo "我是T里面的保护函数:who <br>"; } public function name() { echo "我是T里面的公共函数:name <br>"; } } $test = new T(); $func = Closure::bind(function () { $this->who(); $this->name(); $this->show(); }, $test ); $func();
结果:
Fatal error: Uncaught Error: Call to protected method T::who()
who是protected的,怎么可以在类的外部(类的作用域外)访问呢?,但是我们稍加改造一下:
1 class T { 2 3 private static $name = '我是T里面的私有属性 $name <br>'; 4 5 private function show() { 6 echo "我是T里面的私有函数:show <br>"; 7 } 8 9 protected function who() { 10 echo "我是T里面的保护函数:who <br>"; 11 } 12 13 public function name() { 14 echo "我是T里面的公共函数:name <br>"; 15 } 16 } 17 18 $test = new T(); 19 20 $func = Closure::bind(function () { 21 $this->who(); 22 $this->name(); 23 $this->show(); 24 }, $test, 25 T::class//加这个,指定匿名函数可以使用T这个类的作用域。下面两种方式都可以 26 //'T' 27 //new T() 28 ); 29 30 $func();
结果:
是不是很神奇,类的protected和private的成员也可以在类的外部访问。可以理解为,第三个参数,等于是授权了匿名函数,你可以到某个类的作用域内部来访问类的所有成员(包括静态和非静态)。
那么怎么在匿名函数内,访问静态成员呢?很简单,就和真的在类的内部一样,可以使用[self::]或者[类名::]或者[static::]。
具体:
1 class T { 2 3 private static $name = '我是T里面的私有属性 $name <br>'; 4 5 private function show() { 6 echo "我是T里面的私有函数:show <br>"; 7 } 8 9 protected function who() { 10 echo "我是T里面的保护函数:who <br>"; 11 } 12 13 public function name() { 14 echo "我是T里面的公共函数:name <br>"; 15 } 16 } 17 18 $test = new T(); 19 20 $func = Closure::bind(function () { 21 $this->who(); 22 $this->name(); 23 $this->show(); 24 25 echo self::$name; //访问静态私有成员 26 echo static::$name; //访问静态私有成员 27 }, $test, 28 T::class//加这个,指定匿名函数可以使用T这个类的作用域。下面两种方式都可以 29 //'T' 30 //new T() 31 ); 32 33 $func();
结果: