匿名函数匿名函数,又称闭包函数,简单来说就是“没有名字的函数”。注意:理论上,闭包和匿名函数是不同的概念,但是PHP把它们当成同一个概念。$func=function(){echo'HelloWorld'.PHP_EOL;};$func();匿名函数与普通函数的区别在于:匿名函数也可以作为变量的值。匿名函数可以从父作用域继承变量,父作用域是定义闭包的函数(不一定是调用它的函数)。$message='hello';$example=function()use($message){return$message;};$message='world';回声$例子();输出:hello注意:设置变量必须使用use关键字传入即可,详见官方文档。闭包类定义了一个闭包函数,其实就是实例化一个闭包类(Closure)对象:$func=function(){echo'helloworld'.PHP_EOL;};var_dump($func);输出:object(Closure)#1(0){}类摘要:Closure{__construct(void)publicstaticClosurebind(Closure$closure,object$newthis[,mixed$newscope='static'])publicClosurebindTo(object$newthis[,mixed$newscope='static'])}除了上面的方法,闭包还实现了一个__invoke()魔术方法。当试图以调用函数的方式调用一个对象时,__invoke()方法将被自动调用。bindTo方法接下来,让我们看一下bindTo方法,通过它我们可以将闭包的内部状态绑定到其他对象。bindTo方法的第二个参数在这里尤为重要。它的作用是指定闭包所绑定的对象所属的PHP类,这样闭包就可以在别处访问该闭包所绑定对象的protected和private属性。成员变量。你会发现PHP框架经常使用bindTo方法将路由URL映射到匿名回调函数。框架会将匿名回调函数绑定到应用对象上,这样在匿名函数中就可以使用$this关键字来引用重要的应用对象。:classApp{protected$routes=[];受保护的$responseStatus='200OK';受保护的$responseContentType='text/html';受保护的$responseBody='HelloWorld';publicfunctionaddRoute($path,$callback){$this->routes[$path]=$callback->bindTo($this,__CLASS__);}}publicfunctiondispatch($path){foreach($this->routesas$routePath=>$callback){if($routePath===$path){$callback();}}header('HTTP/1.1'.$this->responseStatus);header('Content-Type:'.$this->responseContentType);header('Content-Length:'.mb_strlen($this->responseBody));echo$this->responseBody;}}这里需要重点关注addRoute方法,该方法的参数是路由路径和路由回调,dispatch方法的参数是当前HTTP请求的路径,会调用匹配的路由回调。第9行是重点,我们给当前的App实例绑定路由回调。这样做可以在回调函数中处理App实例的状态:$app=newApp();$app->addRoute('/user',function(){$this->responseContentType='application/json;charset=utf8';$this->responseBody='Helloworld';});$app->dispatch('/user');IoC容器匿名函数可以从父作用域继承变量,而这个父作用域是定义了闭包的一个函数(不一定是调用它的函数)。使用这个特性,我们可以实现一个简单的控制反转IoC容器:classContainer{protectedstatic$bindings;publicstaticfunctionbind($abstract,Closure$concrete){static::$bindings[$abstract]=$concrete;}publicstaticfunctionmake($abstract){returncall_user_func(static::$bindings[$abstract]);}}classtalk{publicfunctiongreet($target){echo'Hello'.$目标->getName();}}A类{publicfunctiongetName(){return'World';}}//创建类talk的实例$talk=newtalk();//将类A绑定到容器,命名为fooContainer::bind('foo',function(){returnnewA;});//通过容器取出实例$talk->greet(Container::make('foo'));//在上面的HelloWorld例子中,只有通过make方法获取到实例的时候才创建实例,这样我们就可以实现容器了。闭包和bindTo方法在Laravel框架的底层也被广泛使用。善用闭包可以实现事件触发等更高级的功能。以上是闭包学习笔记,部分参考了网上的一些文章。
