PHP 嵌套函数有什么用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/415969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:41:07  来源:igfitidea点击:

What are PHP nested functions for?

phpnested-function

提问by meouw

In JavaScript nested functions are very useful: closures, private methods and what have you..

在 JavaScript 中,嵌套函数非常有用:闭包、私有方法等等。

What are nested PHP functions for? Does anyone use them and what for?

什么是嵌套的 PHP 函数?有没有人使用它们?用于什么?

Here's a small investigation I did

这是我做的一个小调查

<?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()

回答by Martijn Laarman

There is none basically, I've always treated this as a side effect of the parser.

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

Eran Galperin is mistaken that these functions are somehow private, they are simply undeclared until outer()is run. They are also not privately scoped, they do polute the global scope albeit delayed. And as a callback the outer callback could still only be called once. I still don't see how that's helpful applying it on an array which very likely calls the alias more than once.

Eran Galperin 错误地认为这些函数在某种程度上是私有的,它们在outer()运行之前只是未声明的。它们也不是私有范围的,它们确实污染了全局范围,尽管延迟了。作为回调,外部回调仍然只能被调用一次。我仍然不明白将它应用于很可能多次调用别名的数组有什么帮助。

The only 'real world' example I could dig up is thiswhich can only run once and could be rewritten cleaner IMO.

唯一的“现实世界”的例子,我能挖出个是这个只能运行一次,并且可以IMO改写清洁。

The only use I can think of is for modules to call a [name]_include method which sets several nested methods in the global space combined with

我能想到的唯一用途是模块调用 [name]_include 方法,该方法在全局空间中设置几个嵌套方法,并结合

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

checks.

检查。

PHP's OOP would obviously be a better choice :)

PHP 的 OOP 显然是更好的选择 :)

回答by user641463

If you are using PHP 5.3 you can get more Javacript-like behaviour with an anonymous function:

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

<?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
?>

Output:

输出:

test
test

回答by Sz.

[Rewritten according to the comment by @PierredeLESPINAY.]

[根据@PierredeLEESPINAY 的评论重写。]

It's not just a side-effect at all, but actually a very useful feature for dynamically modifyingthe logic of your program. It's from the procedural PHP days, but can come in handy with OO architectures too, if you want to provide alternative implementations for certain standalone functions in the most straightforward way possible. (While OO is the better choice most of the time, it's an option, not a mandate, and some simple tasks don't need the extra cruft.)

它根本不仅仅是一个副作用,而且实际上是动态修改程序逻辑的一个非常有用的功能。它来自程序化 PHP 时代,但如果您想以最直接的方式为某些独立函数提供替代实现,也可以在 OO 架构中派上用场。(虽然 OO 在大多数情况下是更好的选择,但它是一种选择,而不是强制要求,并且一些简单的任务不需要额外的麻烦。)

For example, if you dynamically/conditionally load plugins from your framework, and want to make the life of the plugin authors super easy, you can provide default implementations for some critical functions the plugin didn't override:

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

<?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... ;)
        }
    }
}

回答by cletus

Functions defined within functions I can't see much use for but conditionally defined functions I can. For example:

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

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

And then all your code needs to do is use the 'cmp' function in things like usort() calls so you don't litter language checks all over your code. Now I haven't done this but I can see arguments for doing it.

然后您的代码需要做的就是在诸如 usort() 调用之类的事情中使用 'cmp' 函数,这样您就不会在整个代码中进行语言检查。现在我还没有这样做,但我可以看到这样做的论据。

回答by Anthony Rutledge

All the above being said, one might simply create a nested function to replace some localized, repetitive code within a function (that will only be used inside the parent function). An anonymous function is a perfect example of this.

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

Some might say just create private methods (or smaller code blocks) in a class, but that is muddying the waters when an ultra-specific task (which is exclusive to the parent) needs to be modularized, but not necessarily available to the rest of a class. The good news is if it turns out that you do need that function somewhere else, the fix is rather elementary (move the definition to a more central location).

有些人可能会说只在一个类中创建私有方法(或较小的代码块),但是当一个超特定任务(父级独有)需要模块化时,这就是在搅浑水,但不一定对其余部分可用一类。好消息是,如果事实证明您确实需要在其他地方使用该功能,则修复方法相当简单(将定义移至更中心的位置)。

Generally speaking, using JavaScript as the standard by which to evaluate other C based programming languages is a bad idea. JavaScript is definitely its own animal when compared to PHP, Python, Perl, C, C++, and Java. Of course, there are lots of general similarities, but the nitty, gritty details (reference JavaScript: The Definitive Guide, 6th Edition, Chapters 1-12), when paid attention to, make core JavaScript unique, beautiful, different, simple, and complex all at the same time. That's my two cents.

一般来说,使用 JavaScript 作为评估其他基于 C 的编程语言的标准是一个坏主意。与 PHP、Python、Perl、C、C++ 和 Java 相比,JavaScript 绝对是它自己的动物。当然,它们之间有很多普遍的相似之处,但是在细节上(参考JavaScript: The Definitive Guide, 6th Edition, Chapters 1-12),当注意时,使核心 JavaScript 变得独特、美观、不同、简单和同时复杂。那是我的两分钱。

Just to be clear, I'm not saying nested functions are private. Just that nesting can help avoid clutter when something trivial needs to be modularized (and is only needed by the parent function).

明确地说,我并不是说嵌套函数是私有的。当一些琐碎的事情需要模块化(并且只有父函数需要)时,嵌套可以帮助避免混乱。

回答by Jesse James Richard

All of my php is OO, but I do see a use for nested functions, particularly when your function is recursive and not necessarily an object. That is to say, it does not get called outside of the function it is nested in, but is recursive and subsequently needs to be a function.

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

There's little point in making a new method for the express use of a single other method. To me that's clumsy code and sort-of not the point of OO. If you're never going to call that function anywhere else, nest it.

为明确使用其他单一方法而创建新方法没有什么意义。对我来说,这是笨拙的代码,有点不是面向对象的重点。如果您永远不会在其他任何地方调用该函数,请将其嵌套。

回答by ZhuLien

In webservice calling we found it a much lower overhead (memory and speed) dynamically including in a nested fashion, individual functions over libraries full of 1000s of functions. The typical call stack might be between 5-10 calls deep only requiring linking a dozen 1-2kb files dynamically was better than including megabytes. This was done just by creating a small util function wrapping requires. The included functions become nested within the functions above the call stack. Consider it in contrast to classes full of 100s of functions that weren't required upon every webservice call but could also have used the inbuilt lazy loading features of php.

在 Web 服务调用中,我们发现它的开销(内存和速度)要低得多,动态地包括以嵌套方式、单个函数,而不是包含 1000 多个函数的库。典型的调用堆栈可能在 5-10 次调用之间,只需要动态链接十几个 1-2kb 的文件就比包括兆字节要好。这只是通过创建一个小的 util 函数包装 requires 来完成的。包含的函数嵌套在调用堆栈上方的函数中。将其与充满数百个函数的类形成对比,这些类不是每次 Web 服务调用都需要的,但也可以使用 php 的内置延迟加载功能。

回答by ZhuLien

I know this is an old post but fwiw I use nested functions to give a neat and tidy approach to a recursive call when I only need the functionality locally - e.g. for building hierarchical objects etc (obviously you need to be careful the parent function is only called once):

我知道这是一篇旧帖子,但是当我只需要本地功能时,我使用嵌套函数为递归调用提供了一种整洁的方法 - 例如用于构建分层对象等(显然你需要小心父函数只是调用一次):

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
}

A point of note in php compared with JS for instance is that the call to the nested function needs to be made after, i.e. below, the function declaration (compared with JS where the function call can be anywhere within the parent function

例如,与 JS 相比,php 中的一个注意点是对嵌套函数的调用需要在函数声明之后进行,即在下面(与 JS 相比,函数调用可以在父函数中的任何位置)

回答by princebillyGK

if you are in php 7 then see this:This implementation will give you a clear idea about nested function. Suppose we have three functions(too(), boo() and zoo()) nested in function foo(). boo() and zoo() have same named nested function xoo(). Now in this code I have commented out the rules of nested functions clearly.

如果您使用的是 php 7,那么请查看:此实现将使您对嵌套函数有一个清晰的了解。假设我们在函数 foo() 中嵌套了三个函数(too()、boo() 和 zoo())。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()

    }

Now if we call test1() the output will be this:

现在,如果我们调用 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

if we call test2() the output will be this:

如果我们调用 test2() 输出将是这样的:

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

But we cannot call both text1() and test2() at same time to avoid re-declaration error

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

回答by MJHd

I have only really used this characteristic when it was useful to execute a small recursive function inside a primary, more categorical function, but didn't want to move it to a different file because it was fundamental to the behavior of a primary process. I realize there are other "best practice" ways of doing this, but I want to make sure my devs see that function every time they look at my parser, it's likely what they should modify anyway...

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