PHP 5.3 parte 3: Lambda e Closures
      Exemplos úteis de utilização de Closures
Closures são bastante úteis em funções que utilizam callbacks. Outra forma de tirar proveito de closures é refactorar velhos códigos afim de deixá-los mais limpos. Veja o exemplo abaixo, onde usamos o método Logger::log para logar uma observação para cada query executada no banco de dados:
Refactorando o código acima para utilizar closures deixamos o código mais agradável para ler e entender.
Segue abaixo o código refactorado:
    
  
    
    
  Closures são bastante úteis em funções que utilizam callbacks. Outra forma de tirar proveito de closures é refactorar velhos códigos afim de deixá-los mais limpos. Veja o exemplo abaixo, onde usamos o método Logger::log para logar uma observação para cada query executada no banco de dados:
<?php
$db = mysqli_connect("server","user","pass");
Logger::log('debug','database','Conectando com a base de dados');
$db->query("insert into users (nome, descricao) values ('Douglas','Administrador')");
Logger::log('debug','database','Insert Douglas into to users table');
$db->query("insert into users (nome, descricao) values ('Andréia','Redatora')");
Logger::log('debug','database','Insert Andreia into to users table');
Refactorando o código acima para utilizar closures deixamos o código mais agradável para ler e entender.
Segue abaixo o código refactorado:
<?php
// definindo o closure
$logdb = function ($string) { Logger::log('debug','database',$string); };
$db = mysqli_connect("server","user","pass");
$logdb('Conectando com a base de dados'); // usando o closure
$db->query("insert into users (nome, descricao) values ('Douglas','Administrador')");
$logdb('Insert Douglas into to users table'); // usando closure
$db->query("insert into users (nome, descricao) values ('Andréia','Redatora')");
$logdb('Insert Andreia into to users table'); // usando closure
                  Aliás, o __invoke só é chamado quando a instância é invocada com os parênteses né? Acho que o primeiro exemplo do "$validacao = validacao()" nem funcionaria...
              
      
        05/01/2010 9:40pm
        (~16 anos atrás)
      
    
                  Estive pensando: será que seria uma boa usar o __invoke para retornar a instância de uma classe singleton?
Algo assim:
Ficaria apenas assim:
Não sei se isso tornaria o código menos intuitivo, já que "getInstance" é consagrado.
Mas se formos parar pra pensar: sempre que se usar o __invoke perderemos um pouco da legibilidade, afinal, estaremos omitindo o nome de um método. Afinal, onde este método seria útil?
Quem sabe para métodos que retornam objetos...
Enfim, as vezes o PHP tras umas coisas que nos faz pensar nas novas possibilidades...
      Algo assim:
$validacao = validacao::getInstance();
Ficaria apenas assim:
$validacao = validacao();
Não sei se isso tornaria o código menos intuitivo, já que "getInstance" é consagrado.
Mas se formos parar pra pensar: sempre que se usar o __invoke perderemos um pouco da legibilidade, afinal, estaremos omitindo o nome de um método. Afinal, onde este método seria útil?
Quem sabe para métodos que retornam objetos...
// Obtendo um usuario $usuario = $alguma_coisa->usuario; // Obtendo um usuario com codigo 1 $usuario = $alguma_coisa->usuario(3);
Enfim, as vezes o PHP tras umas coisas que nos faz pensar nas novas possibilidades...
        05/01/2010 9:35pm
        (~16 anos atrás)
      
    

O método __invoke pode ser usado para que uma classe se comporte como um closure. Imagino que a principal utilidade do closure seria em funções que aceitam callback como parâmetro. Funções como array_map, usort, etc.
Vamos supor que você queira criar diversas funções de comparação para utilizar em uma rotina de ordenação, como usort. Você pode criar diversas classes implementando o método __invoke e passar as instâncias dessas classes como parâmetro para a função usort.
Veja o exemplo abaixo para entender melhor:
<?php class testeInvoke { public function __invoke($a, $b) { return(strcmp($a, $b)); } } $o = new testeInvoke(); $array = array ("Ziraldo", "Luiz", "Joao", "Rodrigo", "Alberto"); usort($array, $o); var_dump($array);Criamos uma classe testeInvoke implementando o método mágico __invoke e passamos a sua instância para a função usort ordernar o array.
O resultado do script anterior:
# php invoke.php array(5) { [0]=> string(7) "Alberto" [1]=> string(4) "Joao" [2]=> string(4) "Luiz" [3]=> string(7) "Rodrigo" [4]=> string(7) "Ziraldo" }