Pergunta

Em JavaScript funções aninhadas são muito úteis: fechos, métodos privados e que você tem ..

O que são aninhados funções PHP para? Faz uso qualquer um deles e para quê?

Aqui está uma pequena investigação que fiz

<?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()
Foi útil?

Solução

Não há ninguém, basicamente, eu sempre tratou isso como um efeito colateral do analisador.

Eran Galperin é equivocada de que essas funções são de alguma forma particular, eles estão simplesmente não declarado até outer() é executado. Eles também não são escopo fechado, eles não poluir o escopo global embora atrasado. E como um retorno de chamada a chamada de retorno exterior só podia ser chamado uma vez. Eu ainda não vejo como isso é útil aplicá-lo em uma matriz que muito provavelmente chama o alias mais de uma vez.

O único exemplo 'mundo real' que eu poderia cavar é este que só pode ser executado uma vez e poderia ser reescrito mais limpo IMO.

O único uso que eu posso pensar é para módulos para chamar um [nome] método _Include que define vários métodos aninhados no espaço global combinado com

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

cheques.

OOP do PHP, obviamente, seria uma escolha melhor:)

Outras dicas

Se você estiver usando PHP 5.3 pode receber mais Javacript-como comportamento com uma função anônima:

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

[reescrita de acordo com o comentário de @PierredeLESPINAY.]

Não é apenas um efeito colateral em tudo, mas, na verdade, um recurso muito útil para dinamicamente modificar a lógica do seu programa. É dos dias PHP processuais, mas pode vir a calhar com arquiteturas orientadas a objetos também, se você quiser fornecer implementações alternativas para determinadas funções independentes da forma mais simples possível. (Enquanto OO é a melhor opção na maioria das vezes, é uma opção, não um mandato, e algumas tarefas simples não precisa do cruft extra.)

Por exemplo, se você dinamicamente / condicionalmente carregar plugins do seu quadro, e quer fazer a vida dos autores de plugins super fácil, você pode fornecer implementações padrão para algumas funções críticas do plugin não substituem:

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

funções definidas dentro de funções não posso ver muito uso para, mas funções posso condicionalmente definido. Por exemplo:

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

E, em seguida, todas as suas necessidades de código a fazer é usar a função 'cmp' em coisas como usort chamadas () para que você não fazer verificações língua de areia em todo o seu código. Agora eu não fiz isso, mas eu posso ver argumentos para fazê-lo.

Todo o ser dito acima, pode simplesmente criar uma função aninhada para substituir algum código localizada, repetitivo dentro de uma função (que só vai ser usado dentro da função pai). Uma função anônima é um exemplo perfeito disso.

Alguns poderiam dizer apenas criar métodos privados (ou blocos de código menores) em uma classe, mas que está turvando as águas quando uma tarefa específica ultra-(que é exclusivo para o pai) precisa ser modularizado, mas não necessariamente disponível para o resto de uma classe. A boa notícia é que se ele sair que você precisa fazer essa função em outro lugar, a correção é bastante elementar (mover a definição para um local mais central).

De um modo geral, usando JavaScript como o padrão pelo qual se avalia outras linguagens de programação C com base é uma má idéia. JavaScript é definitivamente o seu próprio animal quando comparado com PHP, Python, Perl, C, C ++ e Java. Claro, há muitas semelhanças gerais, mas os nitty, detalhes arenosos (referência JavaScript: The Definitive Guide, 6ª Edição, Capítulos 1-12 ), quando prestou atenção, make núcleo JavaScript único, bonito, diferente, simples, e todos complexo ao mesmo tempo. Essa é a minha dois centavos.

Apenas para ser claro, eu não estou dizendo funções aninhadas são privados. Só que nidificação pode ajudar a evitar a desordem quando precisa de algo trivial a ser modularizado (e só é necessário para a função de pai).

Todo o meu php é OO, mas vejo um uso para funções aninhadas, particularmente quando sua função é recursiva e não necessariamente um objeto. Ou seja, ele não é chamado fora da função que está aninhado em, mas é recursiva e, posteriormente, precisa ser uma função.

Há pouco ponto em fazer um novo método para o uso expresso de um único outro método. Para mim isso é código desajeitado e espécie de não o ponto de OO. Se você nunca vai chamar essa função em qualquer outro lugar, ninho lo.

Em webservice chamar que encontramos um menor sobrecarga muito (memória e velocidade), incluindo dinamicamente em uma forma aninhada, as funções individuais sobre bibliotecas cheias de 1000s de funções. A pilha de chamadas típico pode ser entre 5-10 chamadas profunda necessitando apenas de vincular arquivos de uma dúzia de 1-2kb dinamicamente era melhor do que inclusive megabytes. Isso foi feito apenas através da criação de um pequeno util função embrulho requer. As funções incluídas tornar aninhada dentro das funções acima a pilha de chamadas. Considerá-lo em contraste com aulas cheias de 100s de funções que não foram necessárias sobre cada chamada webservice, mas também poderia ter usado o carregamento lento inbuilt características do PHP.

Eu sei que este é um post antigo, mas fwiw eu usar funções aninhadas para dar uma abordagem limpa e arrumada para uma chamada recursiva quando eu só precisam da funcionalidade localmente - por exemplo, para a construção de objetos hierárquicos etc (obviamente, você precisa ter cuidado função pai só é chamado uma vez):

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
}

Um ponto de nota em php comparado com JS, por exemplo, é que a chamada para as necessidades da função aninhados para ser feita depois, isto é, abaixo, a declaração de função (em comparação com JS, onde a chamada de função podem estar em qualquer lugar dentro da função pai

se você estiver em php 7, em seguida, ver o seguinte: Esta implementação vai lhe dar uma ideia clara sobre a função aninhada. Suponha que temos três funções (também (), vaia () e zoológico ()) aninhado em função foo (). boo () e zoológico () têm a mesma chamada função xoo aninhada (). Agora, neste código que comentaram as regras de funções aninhadas de forma clara.

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

    }

Agora, se nós chamamos test1 () a saída será a seguinte:

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

Se nós chamamos test2 () a saída será a seguinte:

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

Mas não podemos chamar tanto text1 () e test2 () ao mesmo tempo a erro evitar a re-declaração

Eu realmente apenas utilizado esta característica quando era útil para executar uma pequena função recursiva dentro de uma função primária, mais categórica, mas não queria movê-lo para um arquivo diferente, porque era fundamental para o comportamento de um primário processo. Sei que existem outras maneiras de "melhores práticas" de fazer isso, mas eu quero ter certeza meus devs ver que função cada vez que olhar para o meu analisador, é provável que eles devem modificar de qualquer maneira ...

funções aninhados são úteis em Memoização (caching resultados da função de melhorar o desempenho).

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

funções aninhadas são úteis se você deseja que a função aninhada para utilizar uma variável que foi declarada dentro da função pai.

<?php
ParentFunc();
function ParentFunc()
{
  $var = 5;
  function NestedFunc()
  {
    global $var;
    $var = $var + 5;
    return $var;
  };
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
}
?>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top