在另一个闭包内调用闭包?

时间:2016-01-23 02:52:46

标签: 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);

假设我们在像这样的数组中检索post值

$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"
];

并且目标是验证json数组中是否存在新条目,条件是两个数组是否具有多于2个相似的值,因为我使用$ t_count来计算类似事件的数量。 我写了两个方法来检查,同时将相同的数据传递到数据池。

// $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;
};

第二个是我尝试在每个组件函数上使用lambdas。我尝试将 $ value $ array $ t_count 放入 use()部分作为这些变量存在于 $ db_entry_exist 的范围内,用于数据绑定&amp;依赖注入。当考虑参数(用于函数)与依赖关系(用于使用) h_loop 时,我发现它令人困惑,PHP在实现Javascript概念方面的整个混乱是什么。

无论我传递给函数部分的参数是什么,无论在 use()部分注入了哪些变量。已经测试了许多变体,但它们都没有工作。我通常会收到错误&#39;函数名称必须是字符串&#39; 。在PHP中的另一个闭包内调用闭包似乎不能用作Javascript中的逻辑。每当我试图在<的其他部分传递 $ h_loop($ t_count,$ value,$ array); echo $ factorial(5); 时,它就失败了em> n_loop 功能。我不明白的是 $ 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>

总而言之,主要有两个我不理解且无法解释的问题:

    $ db_entry_exist 方法中
  1. $ n_loop 被调用,但 $ h_loop 不是
  2. $ db_entry_exist 的上下文中,如何传递和传递哪些变量到 function()并将依赖项传递给使用()部分。

    $ n_loop = function(&amp; $ t_count,$ arr,$ array)use(&amp; $ n_loop){} // ------或-------还有很多其他的变化。 $ n_loop = function($ arr,$ array)use(&amp; $ n_loop,&amp; $ t_count){}

  3. 请调查代码并告诉我您的想法。谢谢。

1 个答案:

答案 0 :(得分:1)

您的代码中有两个误解会影响您的理解。

首先: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()列表,则可以按预期调用它。