Um chamável é uma referência a uma função ou a um método que é passada
a outra função como um argumento.
Chamáveis são representados com a declaração de tipo callable.
Criação de chamáveis
Um objeto chamável é um tipo que representa algo que pode ser invocado.
Os objetos invocáveis podem ser passados como argumentos para funções ou métodos que
esperam um parâmetro de função de retorno (callback) ou podem ser invocados diretamente.
O tipo callable não pode ser usado como uma declaração de tipo para propriedades de classe.
Em vez disso, use uma declaração de tipo Closure.
Chamáveis podem ser criados de diferentes formas:
Um objeto Closure pode ser criado usando-se
a sintaxe de função anônima,
de função seta,
de chamável de primeira
classe, ou com o médoto Closure::fromCallable().
Nota:
A sintaxe de chamável de
primeira classe está disponível somente a partir do PHP 8.1.0.
Exemplo #1
Exemplo de função de retorno usando Closure
<?php
// Usando a sintaxe de função anônima
$double1 = function ($a) {
return $a * 2;
};
// Usando a sintaxe de chamável de primeira classe
function double_function($a) {
return $a * 2;
}
$double2 = double_function(...);
// Usando a sintaxe de função seta
$double3 = fn($a) => $a * 2;
// Usando Closure::fromCallable
$double4 = Closure::fromCallable('double_function');
// Usando o closure como uma função de retorno aqui para
// duplicar o tamanho de cada elemento no intervalo
$new_numbers = array_map($double1, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double2, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double3, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double4, range(1, 5));
print implode(' ', $new_numbers);
?>
Saída do exemplo acima no PHP 8.1:
2 4 6 8 10
2 4 6 8 10
2 4 6 8 10
2 4 6 8 10
Um chamável também pode ser uma string contendo o nome de uma função ou
de um método estático.
Qualquer função interna ou definida pelo usuário pode ser utilizada, com exceção dos construtores de linguagem
como: array(), echo,
empty(), eval(),
isset(),
list(), print ou
unset().
Métodos estáticos também podem ser passados sem a instância de um
object dessa classe criando um array com
o nome da classe no índice 0 e o nome do método no índice 1 ou usando
a sintaxe especial com operador de resolução de escopo
:: como em 'ClassName::methodName'.
Um método de um object instanciado pode ser um chamável
quando fornecido como um array com o object no índice 0 e o
nome do método no índice 1.
A principal diferença entre um objeto Closure e o
tipo callable é que um objeto Closure é
independente de escopo e sempre pode ser invocado, enquanto um tipo 'callable' pode ser
dependente de escopo e pode não ser invocado diretamente.
Closure é a maneira preferida de criar objetos chamáveis.
Nota:
Embora os objetos Closure estejam vinculados ao escopo
onde são criados, os objetos chamáveis que referenciam métodos de classe como strings
ou arrays são resolvidos no escopo onde são chamados.
Para criar um objeto chamável a partir de um método privado ou protegido, que pode então ser
invocado de fora do escopo da classe, use
Closure::fromCallable() ou a
sintaxe de chamável de primeira
classe.
O PHP permite a criação de chamáveis que podem ser usados como argumento de função de retorno
mas não podem ser chamadas diretamente.
Essas são funções dependentes do contexto que fazem referência a um método de classe na
hierarquia de herança de uma classe, por exemplo:
'parent::method' ou ["static", "method"].
Nota:
A partir do PHP 8.2.0, chamáveis dependentes de contexto
foram descontinuados. Remova a dependência de contexto substituindo
'parent::method' por
parent::class . '::method' ou use a
sintaxe de chamável
de primeira classe.
Exemplo #2
Invocando vários tipos de chamáveis com call_user_function()
<?php
// Exemplo de função de retorno
function minha_funcao_retorno() {
echo 'olá mundo!', PHP_EOL;
}
// Exemplo de método de retorno
class MinhaClasse {
static function meuMetodoRetorno() {
echo 'Olá Mundo!', PHP_EOL;
}
}
// Tipo 1: Função de Retorno Simples
call_user_func('minha_funcao_retorno');
// Tipo 2: Chamada a métodos estáticos
call_user_func(['MinhaClasse', 'meuMetodoRetorno']);
// Tipo 3: Chamada a métodos de objetos
$obj = new MinhaClasse();
call_user_func([$obj, 'meuMetodoRetorno']);
// Tipo 4: Chamada a métodos estáticos
call_user_func('MinhaClasse::meuMetodoRetorno');
// Tipo 5: Chamada a métodos estáticos usando a palavra-chave ::class
call_user_func([MyClass::class, 'myCallbackMethod']);
// Type 6: Relative static class method call
class A {
public static function quem() {
echo "A\n", PHP_EOL;
}
}
class B extends A {
public static function quem() {
echo "B\n", PHP_EOL;
}
}
call_user_func(['B', 'parent::quem']); // descontinuado a partir do PHP 8.2.0
// Type 7: Objetos que implementam __invoke podem ser utilizados como chamáveis
class C {
public function __invoke($nome) {
echo 'Olá ', $nome;
}
}
$c = new C();
call_user_func($c, 'PHP!');
?>
O exemplo acima produzirá:
olá mundo!
Olá Mundo!
Olá Mundo!
Olá Mundo!
Olá Mundo!
Deprecated: Callables of the form ["B", "parent::who"] are deprecated in script on line 41
A
Olá, PHP!
Nota:
Callbacks registrados
com funções como call_user_func() e call_user_func_array() não serão
chamados se houver uma exceção não capturada que foi lançada em um callback anterior.