在PHP中closures……究竟是什么,他们什么时候需要使用它们?

所以我正在编写一个很好的,最新的,面向对象的时尚。 我经常使用PHP实现的OOP的各个方面,但是我想知道什么时候需要使用闭包。 那里的任何专家都可以揭示什么时候实施closures是有益的?

PHP将在5.3中本地支持闭包。 当你想要一个本地函数只用于一些小的,特定的目的时,closures是很好的。 闭包RFC提供了一个很好的例子:

function replace_spaces ($text) { $replacement = function ($matches) { return str_replace ($matches[1], ' ', ' ').' '; }; return preg_replace_callback ('/( +) /', $replacement, $text); } 

这使您可以在replace_spaces()内部本地定义replacement函数,因此它不是:
1)混淆全局名称空间
2)让人们三年的时间不知道为什么有一个全球定义的function只用于另一个function

它使事情组织起来。 注意函数本身没有名字,它只是被定义并被赋值为$replacement的引用。

但请记住,你必须等待PHP 5.3的:)

当您将来需要一个执行您现在已经决定的任务的function时。

例如,如果读取configuration文件,并且其中一个参数告诉您algorithm的hash_methodmultiply而不是square ,则可以创build一个闭包,在需要散列的地方使用该闭包。

闭包可以在(例如) config_parser() 。 它使用do_hash_method()局部variables(从configuration文件)创build一个名为do_hash_method()的函数。 每当调用config_parser()即使没有在该范围内调用它,它也可以访问config_parser()的局部范围内的variables。

一个充满希望的假设例子:

 function config_parser() { // Do some code here // $hash_method is in config_parser() local scope $hash_method = 'multiply'; if ($hashing_enabled) { function do_hash_method($var) { // $hash_method is from the parent's local scope if ($hash_method == 'multiply') return $var * $var; else return $var ^ $var; } } } function hashme($val) { // do_hash_method still knows about $hash_method // even though it's not in the local scope anymore $val = do_hash_method($val) } 

除了技术细节之外,closures是编程风格的一个基本先决条件,称为function导向编程。 闭包大致用于与在面向对象编程中使用对象相同的东西; 它将数据(variables)与一些代码(一个函数)绑定在一起,然后可以传递到其他地方。 因此,它们会影响您编写程序的方式,或者如果您不改变编写程序的方式,它们根本就没有任何影响。

在PHP的情况下,他们有点奇怪,因为PHP已经在基于类的,面向对象的范例以及较老的过程范例中占据重要地位。 通常,具有闭包的语言具有完整的词法范围。 为了保持向后兼容性,PHP不会得到这个,所以这意味着闭包在这里会比在其他语言中稍微有点不同。 我想我们还没有看到他们将如何使用。

我喜欢troelskn的post提供的背景。 当我想在PHP中使用Dan Udey的例子时,我使用OO策略模式。 在我看来,这比引入一个新的全局函数要好得多,这个函数的行为是在运行时确定的。

http://en.wikipedia.org/wiki/Strategy_pattern

你也可以调用函数和方法,使用一个variables在PHP中保存方法名称,这很好。 所以丹的另一个例子就是这样的:

 class ConfigurableEncoder{ private $algorithm = 'multiply'; //default is multiply public function encode($x){ return call_user_func(array($this,$this->algorithm),$x); } public function multiply($x){ return $x * 5; } public function add($x){ return $x + 5; } public function setAlgorithm($algName){ switch(strtolower($algName)){ case 'add': $this->algorithm = 'add'; break; case 'multiply': //fall through default: //default is multiply $this->algorithm = 'multiply'; break; } } } $raw = 5; $encoder = new ConfigurableEncoder(); // set to multiply echo "raw: $raw\n"; // 5 echo "multiply: " . $encoder->encode($raw) . "\n"; // 25 $encoder->setAlgorithm('add'); echo "add: " . $encoder->encode($raw) . "\n"; // 10 

当然,如果你想让它在任何地方都可用的话,你可以把所有东西都变成静态的。

闭包基本上是一个函数,您可以在一个上下文中编写定义,但在另一个上下文中运行。 Javascript帮助了我很多,理解这些,因为它们被用在JavaScript的全部地方。

在PHP中,由于函数内部的“全局”(或“外部”)variables的范围和可访问性不同,所以它们的效率低于JavaScript。 然而,从PHP 5.4开始,闭包可以在对象中运行时访问$ this对象,这使得它们更加有效。

这就是closures的内容,应该足以理解上面所写的内容。

这意味着应该可以在某个地方编写一个函数定义,并在函数定义中使用$ thisvariables,然后将该函数定义赋值给一个variables(其他人已经给出了语法的示例),然后将该variables传递给一个对象并在对象上下文中调用它,然后函数可以通过$ this访问和操作对象,就好像它只是它的另一个方法,而实际上它不是在该对象的类定义中定义的,而是在其他地方定义的。

如果不是很清楚,那么不用担心,一旦开始使用,就会变得清晰。

这里是closures在php中的例子

 // Author: HishamDalal@gamil.com // Publish on: 2017-08-28 class users { private $users = null; private $i = 5; function __construct(){ // Get users from database $this->users = array('a', 'b', 'c', 'd', 'e', 'f'); } function displayUsers($callback){ for($n=0; $n<=$this->i; $n++){ echo $callback($this->users[$n], $n); } } function showUsers($callback){ return $callback($this->users); } function getUserByID($id, $callback){ $user = isset($this->users[$id]) ? $this->users[$id] : null; return $callback($user); } } $u = new users(); $u->displayUsers(function($username, $userID){ echo "$userID -> $username<br>"; }); $u->showUsers(function($users){ foreach($users as $user){ echo strtoupper($user).' '; } }); $x = $u->getUserByID(2, function($user){ return "<h1>$user</h1>"; }); echo ($x); 

输出:

 0 -> a 1 -> b 2 -> c 3 -> d 4 -> e 5 -> f ABCDEF c