86

JavaScript では、ネストされた関数は非常に便利です: クロージャー、プライベート メソッド、そしてあなたが持っているもの..

ネストされた 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()
4

13 に答える 13

91

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
于 2011-05-20T10:12:32.110 に答える
90

基本的にありません。私は常にこれをパーサーの副作用として扱ってきました。

Eran Galperin は、これらの関数が何らかの形で非公開であると考えるのは誤りです。が実行されるまで、単に宣言されていませんouter()。また、プライベート スコープではありません。遅れていますが、それらはグローバルスコープを汚染します。また、コールバックとして、外側のコールバックは 1 回しか呼び出すことができませんでした。エイリアスを複数回呼び出す可能性が非常に高い配列に適用することがどのように役立つかはまだわかりません。

私が掘り起こすことができる唯一の「現実世界」の例はこれです。これは一度しか実行できず、よりきれいに書き直すことができます、IMO。

私が考えることができる唯一の用途は、モジュールがメソッドを呼び出すこと[name]_includeです。これは、グローバル空間にいくつかのネストされたメソッドを設定し、

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

チェックします。

PHPのOOPは明らかにより良い選択です:)

于 2009-01-06T10:19:22.110 に答える
10

[@PierredeLESPINAY のコメントに従って書き直しました。]

これは単なる副作用ではなく、実際にはプログラムのロジックを動的に変更するための非常に便利な機能です。これは PHP の手続き型の時代のものですが、可能な限り最も簡単な方法で特定のスタンドアロン関数の代替実装を提供したい場合は、オブジェクト指向アーキテクチャでも役立ちます。(ほとんどの場合、オブジェクト指向の方が適切な選択ですが、これは義務ではなくオプションであり、単純なタスクの中には余分な手間が必要ないものもあります。)

たとえば、フレームワークから動的/条件付きでプラグインをロードし、プラグイン作成者の作業を非常に簡単にしたい場合は、プラグインがオーバーライドしなかったいくつかの重要な機能にデフォルトの実装を提供できます。

<?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... ;)
        }
    }
}
于 2013-12-15T12:57:48.780 に答える
8

関数内で定義された関数私はあまり使用されていませんが、条件付きで定義された関数は使用できます。例えば:

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

そして、コードで行う必要があるのは、usort()呼び出しなどで「cmp」関数を使用することだけです。これにより、コード全体で言語チェックが無駄になりません。今、私はこれをしていませんが、それをするための議論を見ることができます。

于 2009-01-06T12:11:45.237 に答える
2

私のphpはすべてOOですが、特に関数が再帰的で必ずしもオブジェクトではない場合、ネストされた関数の使用が見られます。つまり、ネストされている関数の外では呼び出されませんが、再帰的であり、後で関数にする必要があります。

他の単一のメソッドを明示的に使用するために新しいメソッドを作成しても、ほとんど意味がありません。私にとって、それは不器用なコードであり、オブジェクト指向のポイントではありません。その関数を他の場所で決して呼び出さない場合は、ネストしてください。

于 2012-04-30T20:41:51.163 に答える
0

この特性を実際に使用したのは、主要なよりカテゴリカルな関数内で小さな再帰関数を実行するのに便利な場合だけでしたが、主要なプロセスの動作の基本であるため、別のファイルに移動したくありませんでした。これを行うには他の「ベストプラクティス」の方法があることは承知していますが、開発者がパーサーを見るたびにその機能を確認できるようにしたいので、とにかく変更する必要がある可能性があります...

于 2019-02-07T18:10:34.370 に答える
-1

ネストされた関数はメモ化に役立ちます(パフォーマンスを向上させるために関数の結果をキャッシュします)。

<?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);
}
?>
于 2011-05-24T16:56:27.297 に答える
-1

ネストされた関数は、親関数内で宣言された変数をネストされた関数で利用したい場合に便利です。

<?php
ParentFunc();
function ParentFunc()
{
  $var = 5;
  function NestedFunc()
  {
    global $var;
    $var = $var + 5;
    return $var;
  };
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
}
?>
于 2015-11-14T00:39:58.143 に答える