在另一个闭包中调用闭包

  • 本文关键字:闭包 调用 另一个 php
  • 更新时间 :
  • 英文 :


PHP似乎非常不一致,(编译器)无法生成逻辑。让我们开始调查,首先使用一组简单的 JSON 数据。

[
{
    "customer": "cust01",
    "assembly": "assem01",
    "date_received": "02-08-2015",
    "time_received": "09:15",
    "date_completed": "02-23-2015",
    "time_completed": "10:27"
},
{
    "customer": "lov_01",
    "assembly": "lov_02",
    "date_received": "lov_03",
    "time_received": "lov_04",
    "date_completed": "lov05",
    "time_completed": "lov_06"
}

]

然后在 PHP 中,我们检索该数据的数组

    $t_json_string = file_get_contents($t_json_file_path);
    $t_json_arr = json_decode($t_json_string, true);

假设我们在这样的数组中检索帖子值

$t_new_entry = [ 
    "customer"      => "lov_01", 
    "assembly"      => "lov_02",
    "date_received" => "lov_03",
    "time_received" => "lov_04",
    "time_completed"=> "lov_05",
    "time_completed"=> "lov_06"
];

目标是通过两个数组是否具有超过 2 个相似值的条件来验证 JSON 数组中是否存在新条目,为此我使用 $t_count 来计算类似出现的次数。我写了 2 种方法,用于在将相同的数据传递到数据池时进行检查。

// $t_boo = $db_entry_check($t_new_entry, $t_json_arr); echo $t_boo; 
// true, $t_count shows 3.
   $t_bool = $db_entry_exist($t_new_entry, $t_json_arr); echo $t_bool; 
// False. It has to be true with the $t_count printed out at 3.

第一个使用call_user_function_array,我测试了它并且有效,所以我将其注释掉了。在这里为它编写代码:

$db_entry_check = function($needle, $haystack){
    $t_exist = 'false';
    $t_count = 0;
    function h_loop (&$t_count, $value, $array){
        foreach ($array as $key => $val){
            if (is_array($val)){
                h_loop($t_count, $value, $val);
            } else {
                echo "<br/> --- value: ". $value. "<br/> --- val: ". $val . "<br/><br/>";
                if ($val === $value){
                    $t_count += 1;
                    echo "<br/>" . $t_count . "<br/>";
                    continue;
                }
            }
        }
    }
    function n_loop (&$t_count, $arr, $array){
        foreach ($arr as $key => $value){
            if (is_array($value)){
                n_loop($t_count, $value, $array);
            } else {
                if ($t_count > 2) continue;
                call_user_func_array('h_loop', [&$t_count, $value, $array]);
            }
        }
    }
    n_loop($t_count, $needle, $haystack);
    echo "<br/>" . $t_count . "<br/>";
    if ($t_count > 2) $t_exist = 'true';
    return $t_exist;
};

第二个是我尝试在每个组件函数上使用 lambda。我尝试将$value$array$t_count放入use()部分,因为这些变量存在于$db_entry_exist范围内,用于数据绑定和依赖注入。当涉及到考虑参数(用于函数)与依赖项(用于使用)h_loop时,我发现令人困惑,PHP 努力实现 Javascript 概念是多么混乱。

无论我传递给函数部分的参数是什么,也无论在 use() 部分中注入了什么变量。许多变体已经过测试,但没有一个有效。我通常会收到"函数名称必须是字符串"的错误。在PHP中调用另一个闭包中的闭包似乎不像Javascript中的逻辑那样工作。每当我尝试传递 $h_loop($t_count, $value, $array); 或回显 $factorial(5);n_loop 函数的 else 部分时,它都会失败。我不明白的是$db_entry_exist本身是一个lambda(PHP称之为闭包),并且可以在内部调用n_loop函数而没有任何错误,但是通过相同的方法调用/调用孙子(h_loop)函数不起作用,通常会导致上述相同的错误。

    $db_entry_exist = function($needle, $haystack){
    $t_exist = 'false';
    $t_count = 0;
    // n_loop($t_count, $needle, $haystack);
    $h_loop = function (&$t_count, $value, $array) use (&$h_loop) {
        foreach ($array as $key => $val){
            if (is_array($val)){
                h_loop($t_count, $value, $val);
            } else {
                echo "<br/> --- value: ". $value. "<br/> --- val: ". $val . "<br/><br/>";
                if ($val === $value){
                    $t_count += 1;
                    echo "<br/>" . $t_count . "<br/>";
                    continue;
                }
            }
        }
    };
    $factoral = function($n) use (&$factoral) {
      if ($n <= 1)
        return 1;
      else
        return $n * $factoral($n - 1);
    }; // source: https://gist.github.com/superic/8290704
    $n_loop = function (&$t_count, $arr, $array) use (&$n_loop) {
        foreach ($arr as $key => $value){
            if (is_array($value)){
                $n_loop($t_count, $value, $array);
            } else {
                if ($t_count > 2) continue;
                $h_loop($t_count, $value, $array);
            }
        }
    };
    /*$n_loop = function ($arr, $array) use (&$n_loop, &$t_count){
        // echo "<br/> --- nloop.t_count: " . $t_count . "<br/>";
        foreach ($arr as $key => $value){
            if (is_array($value)){
                $n_loop($value);
            } else {
                if ($t_count > 2) continue;
                // $h_loop($value, $array);
            }
        }
    };*/
    $n_loop($t_count, $needle, $haystack);
    echo "<br/>" . $t_count . "<br/>";
    if ($t_count > 2) $t_exist = 'true';
    return $t_exist;
};

这是查看我的整个代码的链接:

<script src="http://ideone.com/e.js/YjLkZF" type="text/javascript" ></script>

综上所述,主要有2个问题我不明白,也想不通:

  1. $n_loop$db_entry_exist方法中被很好地调用,但$h_loop不是。
  2. $db_entry_exists 的上下文中,如何将哪些变量传递给函数 () 并将哪些变量作为依赖项传递给 use() 部分。

    $n_loop = function (&$t_count, $arr, $array) use (&$n_loop){}------或-------许多其他变体也存在。$n_loop = function ($arr, $array) use (&$n_loop, &$t_count){}

请调查代码并让我知道您的想法。谢谢。

你的代码中有两个误解,影响了你的理解。

第一:PHP 实际上没有嵌套函数。当你说:

function outer()
{
    function foo() {}
    function bar() {}
}

你真正想说的是,当调用outer()时,在全局范围内定义foo()bar()。这意味着一旦您呼叫outer()一次,任何人都可以(不仅仅是outer())拨打foo()bar()。这也意味着第二次调用outer()会导致Cannot redeclare foo()错误。

第二:PHP 中的闭包不会自动关闭其父作用域中的任何变量。任何打算成为闭包一部分的变量都必须显式包含在use()列表中。这意味着当您编写:

$n_loop = function (&$t_count, $arr, $array) use (&$n_loop) {
    //...
            $h_loop($t_count, $value, $array);
    //...
};

$h_loop的调用将始终失败,因为在该函数的范围内,没有名为 $h_loop 的变量。如果将$h_loop添加到use()列表中,则可以按预期调用它。

最新更新