Callback é um mecanismo utilizado por uma linguagem para que uma função seja transmitida na forma de parâmetro para outra função. Uma função com comportamento genérico recebe um callback por parâmetro e usa a função callback para realizar as operações específicas. Desta forma, é possível utilizar a função de diferentes formas.
O exemplo mais clássico é o de ordenação de arrays. Para ordenar um array numérico, normalmente usa-se a função sort. Esta função traz embutido dentro dela a estratégia utilizada para se comparar dois valores numéricos ou strings. Basicamente a estratégia é utilizar o operador "<" ou ">" para determinar qual valor é maior ou menor que o outro e aplicar sobre o algoritmo de ordenação.
Porém, a função sort não serve para ordenar um array de objetos, já que o operador "<" ou ">" não funcionaria adequadamente para se comparar dois objetos. Neste caso, é possível implementar uma função que compara dois objetos e passá-la para a função usort. Esta função serve para ordenar um array utilizando um algoritmo informado na forma de callback por parâmetro.
Vejamos um exemplo:
$array = array(); // Criando um array de 100 objetos cujo atributo "valor" e' aleatorio for ($i = 0; $i < 100; $i++) { $obj = new stdClass(); $obj->valor = rand(0, 1000); $array[] = $obj; } // Criando uma função que sabe comparar dois objetos function comparar_objetos($obj1, $obj2) { if ($obj1->valor < $obj2->valor) { return -1; } elseif ($obj1->valor > $obj2->valor) { return +1; } return 0; } // Criando um callback $callback = 'comparar_objetos'; // Usar usort com o callback usort($array, $callback);
Representação de um Callback
As formas mais comuns de se representar um callback são:
- Função: o callback é uma string que guarda o nome da função;
- Método Não Estático: o callback é um array cuja posição zero guarda um objeto e a posição um guarda uma string com o nome do método não estático;
- Método Estático: o callback pode ser uma string que guarda o nome da classe seguido de "::" e seguido do nome do método. Ou pode ser um array cuja posição zero guarda uma string com o nome da classe e a posição um guarda uma string com o nome do método estático. Ou pode ser representado de forma semelhante à representação do método não estático: através de um array com um objeto e o nome de um método estático;
Observações: no PHP 5.3, com o suporte a namespaces, o callback de funções ou métodos estáticos pode precisar do caminho absoluto do namespace onde a função ou a classe foram definidos.
Tanto funções do PHP quanto do usuário podem ser usadas para se montar um callback. Porém, lembre-se que existem elementos da linguagem que se parecem com funções, mas não são. Elas são chamadas "construções da linguagem". Alguns exemplos são: "echo", "isset", "unset", "list", "eval", "include", entre outros. Você deve olhar para uma construção da linguagem e vê-la como se fosse um "if", "while", "foreach", ou semelhante. São elementos da linguagem PHP e NÃO são funções.
Criando uma função genérica
Toda função/método que recebe um parâmetro do pseudo-tipo callback precisa especificar o que o callback recebe por parâmetro e o que ele deve retornar. Isso é importante para que o usuário que utilizar a função/método genérico possa implementar uma função de callback válida. No caso de um algoritmo de ordenação, a função deve receber dois parâmetros de qualquer tipo. Caso o primeiro seja considerado "menor" que o segundo, deve ser retornado um valor negativo. Caso o segundo seja considerado "menor" que o primeiro, deve ser retornado um valor positivo. E caso os elementos sejam considerados "iguais", deve ser retornado o valor zero.
Você é capaz de criar sua própria função que recebe um callback por parâmetro. Para usá-lo, basta chamar a função call_user_func_array ou call_user_func. Outra alternativa é chamar a "função com nome variável". Uma função útil para verificar se o parâmetro informado é um callback válido é a função "is_callable". Normalmente é utilizado este recurso em funções que manipulam arrays ou coleções.
Exemplo de função genérica para obter o menor elemento do array:
/** * Retorna o menor elemento do array de acordo com uma funcao callback * @param array $array Array de qualquer tipo * @param callback $callback Funcao que compara dois elementos do array * @return mixed O menor valor encontrado */ function menor(array $array, $callback) { // Checar parametro if (!is_callable($callback)) { trigger_error('Invalid callback parameter', E_USER_ERROR); return false; } // Obtendo o menor valor list($pos, $menor) = each($array); while (list($pos, $elemento) = each($array)) { // Usando o callback para comparar o elemento corrente com o menor encontrado $comparacao = call_user_func($callback, $elemento, $menor); // Se o elemento corrente e' menor que o menor encontrado, ele passa a ser o menor if ($comparacao < 0) { $menor = $elemento; } } return $menor; }
2 comentários
Incrível, mesmo sendo um artigo de 2010, é um dos poucos artigos sobre assunto.
Parabéns pela didática Rubens
Muito útil, excelente explicação.
Postar um comentário
Nota: fique a vontade para expressar o que achou deste artigo ou do blog.
Dica: para acompanhar as respostas, acesse com uma conta do Google e marque a opção "Notifique-me".
Atenção: o blogger não permite inclusão de tags nos comentários, por isso, use algum site externo para postar seu código com dúvidas e deixe o link aqui. Exemplo: pastebin.com