代码之家  ›  专栏  ›  技术社区  ›  meouw

PHP嵌套函数的用途是什么?

  •  72
  • meouw  · 技术社区  · 16 年前

    嵌套PHP函数的用途是什么?有人使用它们吗?为什么?

    这是我做的一个小调查

    <?php
    function outer( $msg ) {
        function inner( $msg ) {
            echo 'inner: '.$msg.' ';
        }
        echo 'outer: '.$msg.' ';
        inner( $msg );
    }
    
    inner( 'test1' );  // Fatal error:  Call to undefined function inner()
    outer( 'test2' );  // outer: test2 inner: test2
    inner( 'test3' );  // inner: test3
    outer( 'test4' );  // Fatal error:  Cannot redeclare inner()
    
    12 回复  |  直到 14 年前
        1
  •  91
  •   Gus Hogg-Blake    3 年前

    如果您使用的是PHP 5.3,则可以通过匿名函数获得更多类似JavaScript的行为:

    <?php
    function outer() {
        $inner=function() {
            echo "test\n";
        };
    
        $inner();
    }
    
    outer();
    outer();
    
    inner(); //PHP Fatal error:  Call to undefined function inner()
    $inner(); //PHP Fatal error:  Function name must be a string
    ?>
    

    输出:

    test
    test
    
        2
  •  90
  •   SherylHohman David    4 年前

    基本上没有。我一直认为这是解析器的副作用。

    Eran Galperin错误地认为这些功能在某种程度上是私有的。他们只是没有申报,直到 outer() 他跑了。它们也不属于私人范围;它们确实污染了全球范围,尽管有所延误。作为回调,外部回调仍然只能调用一次。我仍然不认为在数组上应用它有什么帮助,因为数组很可能多次调用别名。

    我能找到的唯一“真实世界”的例子是 this

    我能想到的唯一用途是,模块调用 [name]_include

    if (!function_exists ('somefunc')) {
      function somefunc() { }
    }
    

    检查。

        3
  •  10
  •   Sz.    8 年前

    [根据@PierredeLESPINAY的评论改写。]

    程序的逻辑。它起源于程序化PHP时代,但如果您希望以最简单的方式为某些独立函数提供替代实现,那么它也可以在OO体系结构中派上用场。(虽然OO在大多数情况下是更好的选择,但它是一种选择,而不是一种强制,一些简单的任务不需要额外的支持。)

    例如,如果您从框架中动态/有条件地加载插件,并希望使插件作者的生活变得超级简单,您可以为插件未覆盖的某些关键功能提供默认实现:

    <?php // Some framework module
    
    function provide_defaults()
    {
        // Make sure a critical function exists:
        if (!function_exists("tedious_plugin_callback"))
        {
            function tedious_plugin_callback()
            {
            // Complex code no plugin author ever bothers to customize... ;)
            }
        }
    }
    
        4
  •  8
  •   cletus    16 年前

    在函数中定义的函数我看不出有多大用处,但条件定义的函数我可以。例如:

    if ($language == 'en') {
      function cmp($a, $b) { /* sort by English word order */ }
    } else if ($language == 'de') {
      function cmp($a, $b) { /* sort by German word order; yes it's different */ }
    } // etc
    

        5
  •  7
  •   Anthony Rutledge    6 年前

    综上所述,我们可以简单地创建一个嵌套函数来替换函数中的一些本地化的重复代码(只在父函数中使用)。匿名函数就是一个很好的例子。

    有人可能会说只是在类中创建私有方法(或更小的代码块),但当一个超特定的任务(父任务除外)需要模块化,但不一定对类的其余部分可用时,这就把事情弄糟了。好消息是,如果您在其他地方确实需要该函数,那么修复相当简单(将定义移动到更中心的位置)。

    一般来说,使用JavaScript作为评估其他基于C的编程语言的标准是一个坏主意。JavaScript无疑是它自己的动物,它与PHP、Python、Perl、C、C++和java相比较。当然,有很多一般性的相似之处,但本质、细节(参考 JavaScript:权威指南,第6版,第1-12章 )注意,使核心JavaScript同时具有独特、美观、不同、简单和复杂的特性。那是我的两分钱。

    我只是想说清楚,我并不是说嵌套函数是私有的。只是当一些琐碎的东西需要模块化时(并且只有父函数需要),嵌套可以帮助避免混乱。

        6
  •  2
  •   Jesse James Richard    13 年前

    我所有的php都是面向对象的,但我确实看到了嵌套函数的用途,特别是当您的函数是递归函数而不一定是对象时。也就是说,它不会在嵌套的函数之外被调用,而是递归的,因此需要成为函数。

    用一种新的方法来表达另一种方法是毫无意义的。对我来说,这是一个笨拙的代码,并不是面向对象的重点。如果你永远都不会在其他地方调用这个函数,那么就把它嵌套起来。

        7
  •  1
  •   ZhuLien    11 年前

    在webservice调用中,我们发现它的动态开销(内存和速度)要低得多,包括以嵌套方式调用单个函数,而不是调用满1000个函数的库。典型的调用堆栈可能在5-10次调用之间,只需要动态链接十几个1-2kb文件比包含兆字节要好。这是通过创建一个小的util函数完成的。包含的函数嵌套在调用堆栈上方的函数中。与每个WebService调用中不需要的100个函数的类相比,可以考虑使用PHP的内置懒惰加载特性。

        8
  •  1
  •   Prince Billy Graham    6 年前

    如果您使用的是php 7,请参见以下内容: 此实现将使您清楚地了解嵌套函数。 假设我们有三个函数(too()、boo()和zoo())嵌套在函数foo()中。 boo()和zoo()具有相同的命名嵌套函数xoo()。现在在这段代码中,我已经清楚地注释了嵌套函数的规则。

       function foo(){
            echo 'foo() is called'.'<br>';
            function too(){
                echo 'foo()->too() is called'.'<br>';
            }
            function boo(){
                echo 'foo()->boo() is called'.'<br>';
                function xoo(){
                    echo 'foo()->boo()->xoo() is called'.'<br>';
                }
                function moo(){
                    echo 'foo()->boo()->moo() is called'.'<br>';
                }
            }
            function zoo(){
                echo 'foo()->zoo() is called'.'<br>';
                function xoo(){     //same name as used in boo()->xoo();
                    echo 'zoo()->xoo() is called'.'<br>';
                }
            #we can use same name for nested function more than once 
            #but we can not call more than one of the parent function
            }
        }
    
    /****************************************************************
     * TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST *
     ****************************************************************/
        #xoo();//error: as we have to declare foo() first as xoo() is nested in foo()
    
        function test1(){
            echo '<b>test1:</b><br>';
            foo(); //call foo()
            too();
            boo();
            too(); // we can can a function twice
            moo(); // moo() can be called as we have already called boo() and foo()
            xoo(); // xoo() can be called as we have already called boo() and foo()
            #zoo(); re-declaration error
            //we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo()
        }
    
        function test2(){
            echo '<b>test2:</b><br>';
            foo(); //call foo()
            too();
            #moo(); 
            //we can not call moo() as the parent function boo() is not yet called
            zoo(); 
            xoo();
            #boo(); re-declaration error
            //we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo()
    
        }
    

    现在,如果我们调用test1(),则输出如下:

    test1:
    foo() is called
    foo()->too() is called
    foo()->boo() is called
    foo()->too() is called
    foo()->boo()->moo() is called
    foo()->boo()->xoo() is called
    

    如果调用test2(),则输出如下:

    test2:
    foo() is called
    foo()->too() is called
    foo()->zoo() is called
    zoo()->xoo() is called
    

    但我们不能同时调用text1()和test2(),以避免重新声明错误

        9
  •  0
  •   user8333817 user8333817    7 年前

    function main() {
        // Some code
    
        function addChildren ($parentVar) {
            // Do something
            if ($needsGrandChildren) addChildren ($childVar);
        }
        addChildren ($mainVar); // This call must be below nested func
    
        // Some more code
    }
    

        10
  •  0
  •   MJHd    6 年前

    我只在一个主的、更分类的函数中执行一个小的递归函数很有用的时候才真正使用了这个特性,但我不想将它移动到另一个文件中,因为它是主进程行为的基础。我意识到还有其他的“最佳实践”方法可以做到这一点,但我想确保我的开发人员在每次查看我的解析器时都能看到该函数,这可能是他们应该修改的内容。。。

        11
  •  0
  •   Thanasis    3 年前

    对于那些认为嵌套函数没有实际用途的函数。是的,它们有用途,这就是一个例子。

    假设ajax文件my_file.php:

    <?php
    // my_file.php used for ajax
    
    $ajax_json_in = 10; 
    
    function calculations($a, $b)
    {   $result = $a + $b;
        return $result;
    }
    
    $new_result = $ajax_json_in * calculations(1, 2);
    
    $ajax_json_out =  $new_result; 
       
    ?>
    

    下面的示例包含上述文件两次,没有冲突。您可能不想使用ajax调用它,因为在某些情况下,您需要将它直接包含在HTML中。

    <?php
    // include the above file my_file.php instead of ajaxing it
    
    function result1 
    {
        $ajax_json_in = 20; 
        include("my_file.php");
        return $ajax_json_out; 
    }
    
    
    function result2 
    {
        $ajax_json_in = 20; 
        include("my_file.php");
        return $ajax_json_out;
    }
    
    ?>
    

    因此,嵌套函数在现实生活中有着广泛的应用。

    祝您有个美好的一天。

        12
  •  -1
  •   Paul    14 年前

    嵌套函数在记忆(缓存函数结果以提高性能)中很有用。

    <?php
    function foo($arg1, $arg2) {
        $cacheKey = "foo($arg1, $arg2)";
        if (! getCachedValue($cacheKey)) {
            function _foo($arg1, $arg2) {
                // whatever
                return $result;
            }
            $result = _foo($arg1, $arg2);
            setCachedValue($cacheKey, $result);
        }
        return getCachedValue($cacheKey);
    }
    ?>
    
        13
  •  -1
  •   Matthew    9 年前

    如果希望嵌套函数使用父函数中声明的变量,则嵌套函数非常有用。

    <?php
    ParentFunc();
    function ParentFunc()
    {
      $var = 5;
      function NestedFunc()
      {
        global $var;
        $var = $var + 5;
        return $var;
      };
      echo NestedFunc()."<br>";
      echo NestedFunc()."<br>";
      echo NestedFunc()."<br>";
    }
    ?>