通過幾個栗子認識 PHP 閉包
阿新 • • 發佈:2018-12-27
- 通過幾個栗子認識PHP閉包
有收穫的話請加顆小星星,沒有收穫的話可以 反對 沒有幫助 舉報三連
匿名函式(Anonymous functions),也叫閉包函式(closures),允許 臨時建立一個沒有指定名稱的函式。最經常用作回撥函式(callback)引數的值。當然,也有其它應用的情況。
匿名函式目前是通過 Closure 類來實現的。
一、栗子1 用作於回撥
$rs = preg_replace_callback('/-([a-z])/', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
dump($rs); // "helloWorld"
複製程式碼
二、栗子2 用作於變數賦值
$greet = function ($name) {
dump($name);
};
dump($greet instanceof Closure); // true
$greet('PHP'); // "PHP"
複製程式碼
三、栗子3 從父作用域繼承變數
$message = 'hello';
$example = function () use ($message) {
dump($message);
};
dump($example instanceof Closure); // true
$example(); // "hello"
複製程式碼
四、栗子4的前提條件,簡單理解call_user_func_array()
和call_user_func()
方法
1. call_user_func — 把第一個引數作為回撥函式呼叫
function call_user_func (parameter) {}
該方法接收多個引數,第一個就是回撥函式,可以是普通函式
,也可以是閉包函式
,後面的多個引數
都是作為函式回撥使用
$rs = call_user_func(function (...$params) {
return func_get_args();
}, 1, 2, 3);
dump($rs); // [1,2,3]
複製程式碼
2. call_user_func_array — 呼叫回撥函式,並把一個數組引數作為回撥函式的引數
function call_user_func_array (param_arr) {}
該方法接收2個引數,第一個就是回撥函式,可以是普通函式
,也可以是閉包函式
,後面的陣列引數
都是作為函式回撥使用
$rs = call_user_func_array(function (array $params) {
return func_get_args();
}, [1, 2, 3]);
dump($rs); // [1,2,3]
複製程式碼
五、栗子4 繫結閉包在指定物件
樓主見解是將方法繫結到指定類上,使得方法也可以使用類的屬性和方法,非常適合配合__call()
魔術方法和call_user_func_array
方法一起使用
1. Closure::bindTo — 複製當前閉包物件,繫結指定的$this物件和類作用域。
function bindTo(newscope = 'static') { }
<?php
namespace PHP\Demo\Closure;
class ClosureBindTo
{
public function __call($name, $arguments)
{
if (count($arguments) > 1 && $arguments[0] instanceof \Closure) {
return call_user_func_array($arguments[0]->bindTo($this), array_slice($arguments, 1));
}
throw new \InvalidArgumentException("沒有這個方法");
}
}
// 測試
public function testClosureBindTo()
{
$obj = new ClosureBindTo();
$this->assertEquals(2, $obj->add(function (array $params) {
return ++$params[0];
}, [1]));
// 測試同一個例項
$newObj = $obj->test(function (array $params){
return $this;
}, [1]);
$this->assertTrue($newObj instanceof $obj);
}
複製程式碼
2. Closure::bind — 複製一個閉包,繫結指定的$this物件和類作用域。
static function bind(Closure newthis, $newscope = 'static') { }
bind函式是bindTo的靜態表示
<?php
namespace PHP\Demo\Closure;
class ClosureBind
{
private $methods = [];
public function addMethod(string $name, \Closure $callback)
{
if (!is_callable($callback)) {
throw new \InvalidArgumentException("第二個引數有誤");
}
$this->methods[$name] = \Closure::bind($callback, $this, get_class());
}
public function __call(string $name, array $arguments)
{
if (isset($this->methods[$name])) {
return call_user_func_array($this->methods[$name], $arguments);
}
throw new \RuntimeException("不存在方法[{$name}]");
}
}
// 測試
public function testClosureBind()
{
$obj = new ClosureBind();
$obj->addMethod('add', function (array $params) {
return ++$params[0];
});
$this->assertEquals(2, $obj->add([1]));
// 測試同一個例項
$obj->addMethod('test', function (array $params) {
return $this;
});
$this->assertTrue($obj->test([1]) instanceof $obj);
}
複製程式碼