在PHP匿名函数中定义的PHP函数的范围是什么?

问题描述 投票:1回答:1

如果我这样做:

$checkName = function ($value) use ($min, $max)  {
    function lengthTest($string, $min, $max)
    {
        $length = mb_strlen($string, 'UTF-8');
        return ($length >= $min) && ($length <= $max);
    }
};

1)它是合法的PHP吗?而......

2)函数lengthTest()是全局命名空间,还是仅限于$checkName Closure对象?那么它会成为私人会员吗?

3)qazxsw poi可以被引用作为qazxsw poi的回调方法吗?

lengthTest()

4)可以像这样引用filter_var_array()作为$filterInstructionsArray [ 'fName' => ['filter' => FILTER_CALLBACK], 'flags' => FILTER_REQUIRE_SCALAR, 'options' => [$checkName, 'lengthTest']] ]; 的回调函数吗?

lengthTest

参考

关于filter_var_array()的PHP手册说:

任何有效的PHP代码都可能出现在函数内部,甚至是其他函数和类定义。 ... PHP中的所有函数和类都具有全局范围 - 即使它们是在内部定义的,也可以在函数外部调用它们,反之亦然。

关于$filterInstructionsArray [ 'fName' => ['filter' => FILTER_CALLBACK], 'flags' => FILTER_REQUIRE_SCALAR, 'options' => 'lengthTest'] ]; 的PHP手册说:

匿名函数(也称为闭包)允许创建没有指定名称的函数。它们作为回调参数的值非常有用,但它们还有许多其他用途。闭包也可以用作变量的值; PHP自动将这些表达式转换为Closure内部类的实例。为变量分配闭包使用与任何其他赋值相同的语法,包括尾随分号:

感谢您抽出宝贵时间阅读,思考并回答我的问题。我非常感激。

php function scope anonymous-function
1个回答
1
投票

裂缝指关节

从技术上讲,语法是“正确的”(它不会产生致命错误),但PHP的语义使其在当前形式中实际上无意义。让我们先看几件事,即PHP如何处理命名函数到变量的赋值:

user defined functions

函数本身在赋值时执行,其返回值(NULL或其他)被赋给变量。由于我们只分配函数执行的返回值,因此尝试将此变量用作函数名称是没有用的:

anonymous functions

让我们将其与匿名函数的赋值(a.k.a.''Closure')进行对比:

php > echo shell_exec("php -v");
PHP 5.4.16 (cli) (built: Oct 30 2018 19:30:51)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies

php > function speak($arg) {echo "{$arg}\n";}
php > function give($arg) {return $arg;}
php > $speak = speak(4);
4
php > $give = give(4);
php > var_dump($speak);
NULL
php > var_dump($give);
int(4)

与其他语言不同,闭包在PHP中由实际的Object表示。 'use'子句中的变量是在创建Closure时导入的;函数参数(即$ value)在调用Closure时捕获它们的值(因此我们看到它的名称被标记为必需参数而不是静态值)。闭包中引用的语义现在不值得考虑,但如果你想进一步阅读,php > $speak(4); php > $give(4); php > php > $min = 1; $max = 6; php > $checkName = function ($value) use ($min, $max) { php { echo "value: {$value}\n"; php { echo "min: {$min}\n"; php { echo "max: {$max}\n"; php { }; php > var_dump($checkName); object(Closure)#1 (2) { ["static"]=> array(2) { ["min"]=> int(1) ["max"]=> int(6) } ["parameter"]=> array(1) { ["$value"]=> string(10) "<required>" } } 问题的回答是一个很好的开始。

这里的主要内容是Closure对$ checkName的赋值没有执行Closure本身。相反,$ checkName成为一种“别名”,我们可以使用它来通过名称引用此函数:

goat

鉴于PHP对于传递的函数参数的数量有多宽松,零参数执行会返回预期结果:

this

现在让我们更深入地了解一个函数中的函数:

php > $checkName("hello stackoverflow");
value: hello stackoverflow
min: 1
max: 6
php >

到目前为止,这个结果应该有意义。除非明确调用,否则函数不会执行;因为我们调用myOuterFunc并不意味着我们执行其中定义的任何函数代码。这并不是说我们不能:

php > $checkName();
value:
min: 1
max: 6
php >

这让我们回到了基本上你的问题:Closure中的命名函数怎么样?鉴于我们现在发现的关于函数执行的内容,我们可以生成一系列非常可预测的示例:

php > function myOuterFunc($arg) {
php {   function myInnerFunc($arg){
php {     echo "{$arg}\n";
php {   }
php { }
php > $myVal = myOuterFunc("Hello stackoverflow");
php > var_dump($myVal);
NULL
php >

正如预期的那样,Closure中的命名函数代码没有被执行,因为我们没有明确地调用它。

php > function myOuterFunc($arg) {
php {   function myInnerFunc($arg){
php {     echo "{$arg}\n";
php {   }
php {   myInnerFunc($arg);
php { }
php > $myVal = myOuterFunc("Hello stackoverflow");
Hello stackoverflow
php > var_dump($myVal);
NULL
php >

只要我们在调用它之前定义该函数,显式调用内部函数就可以正常工作:

$min = 1; $max = 6;
$checkName = function ($value) use ($min, $max) {
  function question(){echo "How are you\n";}
  echo "value: {$value}\n";
  echo "min: {$min}\n";
  echo "max: {$max}\n";
};
php > $checkName("Hello stackoverflow");
value: Hello stackoverflow
min: 1
max: 6
php >

那么就你的问题而言:

1)是的,这是合法的,你正在尝试的是可能的,但在目前的形式中在语义上毫无意义。

2)Closure中的任何命名函数肯定不驻留在$ global命名空间中,它们在它们定义的Closure的范围内。 FWIW,术语“成员”通常是指类变量(在PHP中通常称为“属性”)。虽然Closures是一个Object,并且允许您复制在类中找到的实例变量的功能,但不应该以任何方式将它们与类混淆或解释。

3/4)不是你如何使用它,不。 Closure之外没有任何内部函数的概念;如果在调用你的Closure代码时,所述代码使用内部函数执行操作,那么他们将看到光明的一天。但是没有直接的方法来引用那些内部函数,就好像它们是在Closure范围之外定义的那样。

换句话说,执行这些内部函数的唯一方法是:a)该代码由Closure的代码专门执行,b)执行所述Closure代码。

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.