Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中的闭包。。。确切地说,它们是什么?您何时需要使用它们?_Php_Oop_Closures - Fatal编程技术网

PHP中的闭包。。。确切地说,它们是什么?您何时需要使用它们?

PHP中的闭包。。。确切地说,它们是什么?您何时需要使用它们?,php,oop,closures,Php,Oop,Closures,所以我正在以一种很好的、最新的、面向对象的方式进行编程。我经常使用PHP实现的OOP的各个方面,但我想知道什么时候可能需要使用闭包。有没有专家能说明什么时候实现闭包有用?什么时候您将来需要一个函数来执行您现在决定的任务 例如,如果您读取一个配置文件,其中一个参数告诉您算法的hash_方法是multiply而不是square,那么您可以创建一个闭包,该闭包将在需要散列某些内容的任何地方使用 可以在(例如)config_parser()中创建闭包;它使用config\u parser()(来自配置文

所以我正在以一种很好的、最新的、面向对象的方式进行编程。我经常使用PHP实现的OOP的各个方面,但我想知道什么时候可能需要使用闭包。有没有专家能说明什么时候实现闭包有用?

什么时候您将来需要一个函数来执行您现在决定的任务

例如,如果您读取一个配置文件,其中一个参数告诉您算法的
hash_方法
multiply
而不是
square
,那么您可以创建一个闭包,该闭包将在需要散列某些内容的任何地方使用

可以在(例如)
config_parser()中创建闭包;它使用
config\u parser()
(来自配置文件)的本地变量创建一个名为
do\u hash\u method()
的函数。无论何时调用
do\u hash\u method()
,它都可以访问
config\u parser()
的本地范围内的变量,即使没有在该范围内调用它

一个很好的假设例子:

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)
}

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


在PHP的上下文中,它们有点奇怪,因为PHP已经非常依赖于基于类的、面向对象的范例,以及较旧的过程范例。通常,具有闭包的语言具有完整的词法范围。为了保持向后兼容性,PHP不会得到这样的结果,因此这意味着闭包在这里将与其他语言略有不同。我想我们还没有看到它们将如何被使用。

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

您还可以使用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

当然,如果您希望它在任何地方都可用,您可以将所有内容都设置为静态…

PHP将在5.3中本机支持闭包。当您想要一个只用于某些小的特定用途的局部函数时,闭包是很好的。该报告提供了一个很好的例子:

function replace_spaces ($text) {
    $replacement = function ($matches) {
        return str_replace ($matches[1], ' ', ' ').' ';
    };
    return preg_replace_callback ('/( +) /', $replacement, $text);
}
这允许您在
replace_spaces()
中本地定义
replacement
函数,因此它不是:
1)将全局命名空间弄乱
2)这让三年来的人们都想知道为什么有一个全局定义的函数只在另一个函数中使用

它使事情井然有序。请注意函数本身是如何没有名称的,它只是定义并指定为对
$replacement
的引用

但请记住,您必须等待PHP5.3:)

您还可以使用关键字
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;  
 }); 

这里给出了一个很好的解释

闭包基本上是一个函数,您在一个上下文中为它编写定义,但在另一个上下文中运行。Javascript在理解这些方面帮助了我很多,因为它们在Javascript中随处可见

在PHP中,由于函数中“全局”(或“外部”)变量的作用域和可访问性的差异,它们不如JavaScript有效。然而,从PHP5.4开始,闭包可以在对象内部运行时访问$this对象,这使它们更加有效

这就是闭包的意义所在,理解上面写的内容就足够了

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


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

下面是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);

基本上,闭包是内部函数,可以访问外部变量,并用作Anonmyos函数(没有任何名称的函数)的回调函数


//输出队长
//若我们将变量作为引用传递为(&$param),那个么输出将是蜘蛛侠;

闭包:

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

A B C D E F 

c
$arr = [1,2,3,3];
$outersScopeNr = 2;

// The second arg in array_filter is a closure
// It would be inconvenient to have this function in global namespace
// The use keyword lets us access a variable in an outer scope
$newArr = array_filter($arr, function ($el) use ($outersScopeNr) {
    return $el === 3 || $el === $outersScopeNr;
});

var_dump($newArr);
// array (size=3)
//  1 => int 2
//  2 => int 3
//  3 => int 3
MDN对IMO有最好的解释:

闭包是捆绑在一起的函数的组合(封闭) 引用其周围的状态(词汇环境)。在里面 换句话说,闭包允许您访问外部函数的作用域 从内部功能

i、 闭包是一个可以访问父范围内变量的函数。闭包使我们能够方便地动态创建函数,因为在某些情况下,函数只需要在一个地方(回调、可调用参数)

示例:

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

A B C D E F 

c
$arr = [1,2,3,3];
$outersScopeNr = 2;

// The second arg in array_filter is a closure
// It would be inconvenient to have this function in global namespace
// The use keyword lets us access a variable in an outer scope
$newArr = array_filter($arr, function ($el) use ($outersScopeNr) {
    return $el === 3 || $el === $outersScopeNr;
});

var_dump($newArr);
// array (size=3)
//  1 => int 2
//  2 => int 3
//  3 => int 3

我不能简单地复制粘贴这个示例并运行它。我喜欢一个简单的例子,这个答案很差。这是一句毫无意义的话:“当你需要一个f