PHP 中的闭包……确切地说,它们是什么以及何时需要使用它们?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/146737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Closures in PHP... what, precisely, are they and when would you need to use them?
提问by rg88
So I'm programming along in a nice, up to date, object oriented fashion. I regularly make use of the various aspects of OOP that PHP implements but I am wondering when might I need to use closures. Any experts out there that can shed some light on when it would be useful to implement closures?
所以我正在以一种很好的、最新的、面向对象的方式进行编程。我经常使用 PHP 实现的 OOP 的各个方面,但我想知道什么时候可能需要使用闭包。有没有专家可以说明什么时候实施闭包是有用的?
采纳答案by dirtside
PHP will support closures natively in 5.3. A closure is good when you want a local function that's only used for some small, specific purpose. The RFC for closuresgive a good example:
PHP 将在 5.3 中原生支持闭包。当你想要一个只用于一些小的、特定目的的局部函数时,闭包是很好的。闭包的RFC给出了一个很好的例子:
function replace_spaces ($text) {
$replacement = function ($matches) {
return str_replace ($matches[1], ' ', ' ').' ';
};
return preg_replace_callback ('/( +) /', $replacement, $text);
}
This lets you define the replacementfunction locally inside replace_spaces(), so that it's not:
1)Cluttering up the global namespace
2)Making people three years down the line wonder why there's a function defined globally that's only used inside one other function
这让您可以replacement在 内部本地定义函数replace_spaces(),这样它就不会:
1)弄乱全局命名空间
2)让人们三年后想知道为什么有一个全局定义的函数只在另一个函数中使用
It keeps things organized. Notice how the function itself has no name, it simply is defined and assigned as a reference to $replacement.
它使事情井井有条。请注意函数本身是如何没有名称的,它只是被定义并分配为对 的引用$replacement。
But remember, you have to wait for PHP 5.3 :)
但请记住,您必须等待 PHP 5.3 :)
You can also access variables outside it's scope into a closure using the keyword use. Consider this example.
您还可以使用关键字将其范围之外的变量访问到闭包中use。考虑这个例子。
// Set a multiplier
$multiplier = 3;
// Create a list of numbers
$numbers = array(1,2,3,4);
// Use array_walk to iterate
// through the list and multiply
array_walk($numbers, function($number) use($multiplier){
echo $number * $multiplier;
});
An excellent explanation is given here What are php lambdas and closures
这里给出了一个很好的解释什么是 php lambdas 和闭包
回答by Dan Udey
When you will need a function in the future which performs a task that you have decided upon now.
当您将来需要一个函数来执行您现在决定的任务时。
For example, if you read a config file and one of the parameters tells you that the hash_methodfor your algorithm is multiplyrather than square, you can create a closure that will be used wherever you need to hash something.
例如,如果您阅读了一个配置文件并且其中一个参数告诉您hash_methodfor 您的算法是multiply而不是square,您可以创建一个闭包,该闭包将在您需要散列的任何地方使用。
The closure can be created in (for example) config_parser(); it creates a function called do_hash_method()using variables local to config_parser()(from the config file). Whenever do_hash_method()is called, it has access to variables in the local scope ofconfig_parser()even though it's not being called in that scope.
可以在(例如)中创建闭包config_parser();它创建一个do_hash_method()使用本地变量config_parser()(来自配置文件)调用的函数。无论何时do_hash_method()被调用,它都可以访问本地范围内的变量,config_parser()即使它没有在该范围内被调用。
A hopefully good hypothetical example:
一个希望很好的假设示例:
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)
}
回答by troelskn
Apart from the technical details, closures are a fundamental pre-requisite for a programming style known as function oriented programming. A closure is roughly used for the same thing as you use an object for in object oriented programming; It binds data (variables) together with some code (a function), that you can then pass around to somewhere else. As such, they impact on the way that you write programs or - if you don't change the way you write your programs - they don't have any impact at all.
除了技术细节之外,闭包是称为面向函数编程的编程风格的基本先决条件。闭包的用途与面向对象编程中使用对象的用途大致相同;它将数据(变量)与一些代码(函数)绑定在一起,然后您可以将其传递到其他地方。因此,它们会影响您编写程序的方式,或者——如果您不改变编写程序的方式——它们根本不会产生任何影响。
In the context of PHP, they are a little odd, since PHP already is heavy on the class based, object oriented paradigm, as well as the older procedural one. Usually, languages that have closures, has full lexical scope. To maintain backwards compatibility, PHP is not going to get this, so that means that closures are going to be a little different here, than in other languages. I think we have yet to see exactly how they will be used.
在 PHP 的上下文中,它们有点奇怪,因为 PHP 已经很重视基于类的、面向对象的范式,以及较旧的程序范式。通常,具有闭包的语言具有完整的词法范围。为了保持向后兼容性,PHP 不会得到这个,所以这意味着这里的闭包将与其他语言略有不同。我认为我们还没有确切地看到它们将如何使用。
回答by grossvogel
I like the context provided by troelskn's post. When I want to do something like Dan Udey's example in PHP, i use the OO Strategy Pattern. In my opinion, this is much better than introducing a new global function whose behavior is determined at runtime.
我喜欢 troelskn 的帖子提供的上下文。当我想在 PHP 中执行类似 Dan Udey 的示例时,我使用 OO 策略模式。在我看来,这比引入一个在运行时确定其行为的新全局函数要好得多。
http://en.wikipedia.org/wiki/Strategy_pattern
http://en.wikipedia.org/wiki/Strategy_pattern
You can also call functions and methods using a variable holding the method name in PHP, which is great. so another take on Dan's example would be something like this:
您还可以在 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
of course, if you want it to be available everywhere, you could just make everything static...
当然,如果您希望它随处可用,您可以将所有内容设为静态...
回答by Rolf
A closure is basically a function for which you write the definition in one context but run in another context. Javascript helped me a lot with understanding these, because they are used in JavaScript all over the place.
闭包基本上是一个函数,您在一个上下文中为其编写定义但在另一个上下文中运行。Javascript 对我理解这些帮助很大,因为它们在 JavaScript 中无处不在。
In PHP, they are less effective than in JavaScript, due to differences in the scope and accessibility of "global" (or "external") variables from within functions. Yet, starting with PHP 5.4, closures can access the $this object when run inside an object, this makes them a lot more effective.
在 PHP 中,它们不如在 JavaScript 中有效,因为函数内部的“全局”(或“外部”)变量的范围和可访问性存在差异。然而,从 PHP 5.4 开始,闭包在对象内部运行时可以访问 $this 对象,这使得它们更加有效。
This is what closures are about, and it should be enough to understand what is written above.
这就是闭包的含义,理解上面写的内容应该就足够了。
This means that it should be possible to write a function definition somewhere, and use the $this variable inside the function definition, then assign the function definition to a variable (others have given examples of the syntax), then pass this variable to an object and call it in the object context, the function can then access and manipulate the object through $this as if it was just another one of it's methods, when in fact it's not defined in the class definition of that object, but somewhere else.
这意味着应该可以在某处写一个函数定义,并在函数定义内部使用 $this 变量,然后将函数定义赋值给一个变量(其他人已经给出了语法示例),然后将该变量传递给一个对象并在对象上下文中调用它,然后该函数可以通过 $this 访问和操作对象,就好像它只是它的另一个方法一样,而实际上它不是在该对象的类定义中定义的,而是在其他地方定义的。
If it's not very clear, then don't worry, it will become clear once you start using them.
如果不是很清楚,那么不要担心,一旦开始使用它们就会变得清晰。
回答by Harsh Gehlot
Bascially,Closure are the inner functions tat have access to the outer variables and are used as a callback function to anonmyous function (functions that do not have any name).
基本上,闭包是内部函数,可以访问外部变量,并用作匿名函数(没有任何名称的函数)的回调函数。
<?php
$param='ironman';
function sayhello(){
$param='captain';
$func=function () use ($param){
$param='spiderman';
};
$func();
echo $param;
}
sayhello();
?>
//output captain
//and if we pass variable as a reference as(&$param) then output would be spider man;
回答by Hisham Dalal
Here are examples for closures in php
以下是 php 中的闭包示例
// Author: [email protected]
// 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);
Output:
输出:
0 -> a
1 -> b
2 -> c
3 -> d
4 -> e
5 -> f
A B C D E F
c

