匿名函数

匿名函数,也叫闭包函数,说白了就是“没有名字的函数”,和一般函数结构一样,只是少了函数名以及最后需要加上分号;。

注:理论上讲闭包和匿名函数是不同的概念,不过PHP将其视作相同的概念。

$func = function()
{echo 'Hello World' . PHP_EOL;
};
$func();

匿名函数和普通函数的区分有:

  • 匿名函数也可以作为变量的值来使用。
  • 匿名函数可以从父作用域继承变量,而这个父作用域是定义该闭包的函数(不一定是调用它的函数)。
$message = 'hello';
$example = function () use ($message) {return $message;
};
$message = 'world';
echo $example();输出:hello

注意:必须使用use关键字将变量传递进去才行,具体见官方文档。

闭包类

定义一个闭包函数,其实就是实例化一个闭包类(Closure)对象:

$func = function()
{echo 'hello world' . PHP_EOL;
};
var_dump($func);输出:
object(Closure)#1 (0) {
}

类摘要:

Closure {__construct ( void )public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )public Closure bindTo ( object $newthis [, mixed $newscope = 'static' ] )
}

除了以上方法,闭包还实现了一个__invoke()魔术方法,当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

bindTo 方法

接下来我们来看看bindTo方法,通过该方法,我们可以把闭包的内部状态绑定到其他对象上。这里bindTo方法的第二个参数显得尤为重要,其作用是指定绑定闭包的那个对象所属的PHP类,这样,闭包就可以在其他地方访问绑定闭包的对象中受保护和私有的成员变量。

你会发现,PHP框架经常使用bindTo方法把路由URL映射到匿名回调函数上,框架会把匿名回调函数绑定到应用对象上,这样在匿名函数中就可以使用$this关键字引用重要的应用对象:

class App {protected $routes = [];protected $responseStatus = '200 OK';protected $responseContentType = 'text/html';protected $responseBody = 'Hello World';public function addRoute($path, $callback) {$this->routes[$path] = $callback->bindTo($this, __CLASS__);}public function dispatch($path) {foreach ($this->routes as $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 = new App();
$app->addRoute(‘/user’, function(){$this->responseContentType = ‘application/json;charset=utf8’;$this->responseBody = '世界你好';
});
$app->dispatch('/user');

IoC 容器

匿名函数可以从父作用域继承变量,而这个父作用域是定义该闭包的函数(不一定是调用它的函数)。

利用这个特性,我们可以实现一个简单的控制反转IoC容器:

class Container
{protected static $bindings;public static function bind($abstract, Closure $concrete){static::$bindings[$abstract] = $concrete;}public static function make($abstract){return call_user_func(static::$bindings[$abstract]);}
}class talk
{public function greet($target){echo 'Hello ' . $target->getName();}
}class A
{public function getName(){return 'World';}
}// 创建一个talk类的实例
$talk = new talk();// 将A类绑定至容器,命名为foo
Container::bind('foo', function() {return new A;
});// 通过容器取出实例
$talk->greet(Container::make('foo')); // Hello World

上述例子中,只有在通过make方法获取实例的时候,实例才被创建,这样使得我们可以实现容器。

在Laravel框架底层也大量使用了闭包以及bindTo方法,利用好闭包可以实现更多的高级特性如事件触发等。

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要戳这里PHP进阶架构师>>>视频、面试文档免费获取

或 者关注我每天分享技术文章

PHP架构师之路​www.zhihu.com

作者:枫恋寒
来源:简书
地址:https://www.jianshu.com/p/3297b2458608

php object 对象不存在。增加对象_PHP 闭包那点事儿相关推荐

  1. php object 对象不存在。增加对象_PHP开发自己的框架,这些知识点不能错过

    一.PHP常用的四种数据结构 简介:spl是php的一个标准库. <?php//spl(php标准库)数据结构/*** 栈(先进后出)*/ $stack = new SplStack(); $s ...

  2. php object 对象不存在。增加对象_PHP核心

    1.单例模式 单例模式三要素: 拥有一个构造函数,并且为private 拥有一个静态成员变量来保持类的实例 拥有一个访问这个实例的静态方法 <?php //Instan.php 单例类class ...

  3. 例解List<Map<String, Object>>存放的对象问题

    一.提出问题 代码一: import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java ...

  4. Object.assign()合并多个对象

    Object.assign() 作用:合并多个对象. 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 现有对象A,对象B,如果要把A对象的属性的值复制到B上,可以使用Ob ...

  5. Object数据转化为Map对象

    使用request的getParameterMap(),将前段ajax传递的Object数据转化为Map对象 import java.util.HashMap; import java.util.It ...

  6. 关于jQuery对象(类数组对象)以及DOM对象相互转化问题——[object Object]和[object HTMLInputElement]

    之前在某官网课程上看有关jQuery和bootstrap的相关教程,有一节课是教我们如何制作价格菜单的按钮以及总价问题 选中按钮,按钮样式会发生变化,右上角价格会自动运算 6个菜单的html结构差不多 ...

  7. python的可变对象和不可变对象

    说明 在python中处处皆对象,那么具体细分又可以分为可变类型和不可变类型对象,今天来详细讨论一下. is 和 == 的区别 先提前说一下is和==的区别以帮助理解. is是判断两者是否属于同一内存 ...

  8. json转java对象_json转java对象

    1.DTO:Data Transfer Object,数据传送对象 2.对于日期格式的问题,也已经处理 3.json-lib-2.2.2-jdk13.jar (2.1在日期数组 json->ja ...

  9. JavaScript中本地对象、内置对象和宿主对象

    http://www.jianshu.com/p/a52e6e183427 http://blog.csdn.net/weiyastory/article/details/52837466 http: ...

最新文章

  1. 点赞模块设计:Redis缓存 + 定时写入数据库实现高性能点赞功能
  2. 明天参加SmartClient讲座苏州站的来报个名,认识认识。
  3. Linux环境下gcc编译链接库-lz -lrt -lm -lc都是什么库?
  4. 20169217 《Linux内核原理与分析》第七周作业
  5. mysql数据库通过二进制 -【恢复数据记录】
  6. 光伏电站清扫机器人_轻型光伏电站清扫机器人的制作方法
  7. Combine two strings into one.
  8. matlab the installer cannot read,MATLAB安装 The installer cannot read the mwinstall.dll… | 学步园...
  9. Windows完全卸载oracle11g步骤
  10. android listview动态添加viewpager,请教大神,android如何在viewpager里添加listview,谢谢啦...
  11. C++11 继承构造函数
  12. axis1.4 java.sql_web Service问题。。。用axis1.4求帮助
  13. C语言制作科学计算器
  14. 基于JAVA《Python程序设计》教辅系统计算机毕业设计源码+系统+lw文档+部署
  15. 群表示论之二面体群的不可约实表示的求法
  16. 华为电脑怎么把虚拟化打开_电脑怎么在bios开启虚拟化?
  17. 机器学习之GD、SGD
  18. 架构师必须了解的 5 种最佳软件架构模式
  19. MySql-主从复制
  20. 知云文献翻译安装及使用教程

热门文章

  1. vue3,vite2,json数据通过拼接显示链接src
  2. api postmain 鉴权_API鉴权
  3. python杨辉三角_python中的部分高级特性
  4. 大楼通信综合布线系统_建筑智能化,智能大楼防雷系统设计在综合布线中的重要性...
  5. hnu 暑期实训之相同生日
  6. string转换函数以及hnu暑期实训部分和A+B的例题
  7. 牛客寒假算法基础训练营6
  8. 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛——J题 这是一题简单的模拟
  9. Python之编写函数
  10. 将截断字符串或二进制数据。