Dia 7 — Funções: PHP e MySQL
Declarar funções
Declarar funções
Uma função é um bloco de código com nome, parâmetros e retorno. Serve para nomear uma lógica, evitar repetição e passar um comportamento para outra parte do código aceitar. Em PHP, a declaração usa function, o nome vem depois e o corpo fica entre chaves.
Como se usa
function somar(int $a, int $b): int { return $a + $b; } echo somar(10, 5); // 15
- Parâmetro é o nome declarado na assinatura (
$a). Argumento é o valor passado na chamada (10). O manual chama qualquer um de parâmetro; a distinção importa para ler a chamada. - O corpo só roda quando a função é chamada. Uma função declarada e nunca chamada não produz efeito, nem erro.
returnencerra a função e entrega o valor. Semreturn, a função devolvenullimplicitamente.- O tipo declarado depois dos dois-pontos é o tipo de retorno:
: int,: string,: void,: array,: bool,: float. voidsignifica que a função não devolve nada. Ela serve para efeito colateral (imprimir, gravar, mexer em array por referência), ereturn;sozinho é permitido.
Escopo
Variável de fora não entra na função. $taxa = 0.15; não existe dentro de uma função que não a recebeu como argumento — ler $taxa lá dentro é erro de *undefined variable*. Tudo que a função usa, ela recebe por argumento, e o que ela produz, devolve por return.
function total(float $preco, float $taxa): float { return $preco * (1 + $taxa); }
Para um valor fixo que não muda, use const no topo do arquivo ou um static dentro da função. const declarado dentro do corpo de uma função é erro de sintaxe.
Como declarar bem
| Situação | Como |
|---|---|
| Lógica reaproveitada em dois lugares | function nomeada no topo do arquivo ou em arquivo próprio |
| Bloco longo dentro de outra função | função aninhada, se só é usada ali |
| Lógica que só existe como valor | closure, que é a aula do dia 8 |
| Configuração que não muda | const ou define, não função |
| Detalhe | Comportamento |
|---|---|
| Nome de função | case-insensitive: SOMAR() e somar() são a mesma função |
| Declaração repetida | erro fatal *Cannot redeclare* |
Função chamada antes da linha function | funciona: funções são carregadas antes da execução |
Função dentro de if ou foreach | só existe depois que o bloco roda; chamar antes é erro |
return no meio | ignora todo o código que vem depois dentro da função |
Funções não fazem parte do objeto. Não dá
require"dentro" de uma função para importar coisa: oincluderoda no escopo da função e as funções importadas ficam restritas a ela.
Exemplo
<?php // ============================================================ // AULA 1 - Declarar funcoes: function, return e escopo // ============================================================ declare(strict_types=1); // Uma funcao tem nome, parametros e retorno. O parametro e o nome // declarado; o argumento e o valor passado na chamada. function somar(int $a, int $b): int { return $a + $b; } echo "somar(10, 5): " . somar(10, 5) . "\n"; // Passar float onde se espera int lanca TypeError: a funcao nao converte. echo "somar(0.5, 0.25) com parametro int: "; try { somar(0.5, 0.25); } catch (TypeError $erro) { echo $erro->getMessage() . "\n"; } // Sem return, a funcao devolve null implicitamente. function cumprimentar(string $nome): void { echo " Ola, $nome!\n"; } echo "\nFuncao void (nao devolve valor):\n"; cumprimentar('Ana'); cumprimentar('Bruno'); var_dump(cumprimentar('Carla')); // devolve null // return no MEIO da funcao encerra tudo: o que vier depois e ignorado. function classifica(float $nota): string { if ($nota >= 7.0) { return 'aprovado'; } if ($nota >= 5.0) { return 'recuperacao'; } return 'reprovado'; } echo "\nClassificacao:\n"; foreach ([9.5, 6.0, 3.0] as $nota) { echo " nota $nota: " . classifica($nota) . "\n"; } // Escopo: variavel de fora NAO entra na funcao. $taxa = 0.15; echo "\nTaxa visivel aqui fora: $taxa\n"; function aplicarTaxa(float $valor, float $taxa): float { // echo $taxa; // daria erro: undefined variable return $valor * (1 + $taxa); } echo "Total com a taxa passada como argumento: " . aplicarTaxa(100.00, $taxa) . "\n"; // A mesma logica com a taxa fixa dentro da funcao, sem vir de fora. function totalComTaxaFixa(float $preco): float { return $preco * 1.15; } echo "Total com taxa fixa interna: " . totalComTaxaFixa(100.00) . "\n\n"; // Funcao declarada DEPOIS da chamada: funciona, porque o PHP carrega // as funcoes declaradas no arquivo antes de executar o codigo. echo "Chamada antes da declaracao: " . areaRetangulo(3, 4) . "\n"; function areaRetangulo(int $base, int $altura): int { return $base * $altura; } // Nome de funcao nao diferencia maiusculas: SOMAR() e somar() sao a mesma. echo "\nsomar e SOMAR sao a mesma funcao: " . SOMAR(2, 3) . "\n"; // Funcao aninhada: so existe dentro da externa e so depois que ela roda. function processar(array $itens): array { function somentePositivo(int $n): bool { return $n > 0; } return array_values(array_filter($itens, 'somentePositivo')); } echo "\nAninhada (definida dentro da funcao): " . implode(', ', processar([-2, 5, 0, 7, -1, 3])) . "\n";
Saída real
somar(10, 5): 15 somar(0.5, 0.25) com parametro int: somar(): Argument #1 ($a) must be of type int, float given, called in /w/aula1.php on line 19 Funcao void (nao devolve valor): Ola, Ana! Ola, Bruno! Ola, Carla! NULL Classificacao: nota 9.5: aprovado nota 6: recuperacao nota 3: reprovado Taxa visivel aqui fora: 0.15 Total com a taxa passada como argumento: 115 Total com taxa fixa interna: 115 Chamada antes da declaracao: 12 somar e SOMAR sao a mesma funcao: 5 Aninhada (definida dentro da funcao): 5, 7, 3
Tipos de parâmetro e retorno
Tipos de parâmetro e retorno
Com declare(strict_types=1) no topo, os tipos declarados na assinatura passam a valer de verdade: o PHP passa a recusar valores do tipo errado em vez de convertê-los sozinho. É a linha que separa código previsível de código que aceita "5" onde se espera 5.
Como se usa
declare(strict_types=1); function(float $preco, int $qtd, string $cupom = ''): float
O declare é por arquivo, não por função: vale para todas as chamadas feitas dentro daquele arquivo, e só para chamadas feitas a partir dele. O tipo do argumento é conferido no momento da chamada.
Tipos que se pode declarar
| Tipo | Aceita | Observação |
|---|---|---|
int | inteiro | 4, -7 |
float | real | 4.5; um int é aceito onde se espera float |
string | texto | |
bool | verdadeiro ou falso | |
array | array | qualquer dos três formatos |
mixed | qualquer valor | o que o PHP chamava de "sem tipo" |
void | só no retorno | a função não devolve nada |
never | só no retorno | a função sempre lança erro e nunca devolve |
object | qualquer objeto | |
callable | função que pode ser chamada | parâmetro ou retorno |
? antes do tipo | anulável | ?string aceita string e null |
int ou string | união | aceita um dos tipos listados, até 8 |
União e interseção
A união (|) é a alternativa ao PHP 8.0 e resolve a função que aceitava int ou null sem transformar tudo em mixed. A interseção (&) é o espelho, disponível do PHP 8.1, e serve para objeto que precisa implementar duas ou mais interfaces ao mesmo tempo: Countable&ArrayAccess.
O que acontece na hora de errar
| Situação | O que o PHP faz |
|---|---|
f(int $n) chamada com "texto" | TypeError |
f(int $n) chamada com "5" | TypeError (com strict_types, sem ele aceitaria) |
f(int $n): string que devolve 5 | TypeError no return |
f(?int $n) chamada com null | aceita |
f(int $n) chamada com 4.5 | TypeError, mesmo sem strict_types: float para int é perda de informação |
f(float $n) chamada com 4 | aceita, o int é promovido a float |
O TypeError é uma exceção e sai do script se ninguém tratar. A forma de tratar é o try/catch, ou a checagem antes da chamada, com is_int, is_string e afins.
Sem
declare(strict_types=1),f(int $n)chamada com"5"converte e roda; com odeclareno arquivo, ela lançaTypeError. A mesma assinatura se comporta de dois jeitos dependendo de uma linha no topo do arquivo — por isso ele vai no primeiro arquivo, e não em todos.
Exemplo
<?php // ============================================================ // AULA 2 - Tipos de parametro e retorno // ============================================================ declare(strict_types=1); // Com strict_types, o tipo declarado na assinatura passa a valer. // Sem ele, o PHP converte o valor sozinho e aceita "5" onde quer 5. function somar(int $a, int $b): int { return $a + $b; } // int e aceito onde se espera float: o int e promovido, sem perda. function media(float $a, float $b): float { return ($a + $b) / 2; } echo "somar(10, 5) com dois int: " . somar(10, 5) . "\n"; echo "media(7, 5) com int em parametro float: " . media(7, 5) . "\n\n"; // O tipo errado lanca TypeError, que sai do script se ninguem tratar. echo "Passando string onde se espera int:\n"; try { somar('dez', 5); } catch (TypeError $erro) { echo " TypeError: " . $erro->getMessage() . "\n"; } echo "\nPassando float com parte decimal onde se espera int:\n"; try { somar(4.5, 5); } catch (TypeError $erro) { echo " TypeError: " . $erro->getMessage() . "\n"; } // Um unico tipo de letra, dois retornos validos: union type (? e |). function describe(?int $codigo): string { return $codigo === null ? 'sem codigo' : "codigo $codigo"; } function somaOuTexto(int|float $a, int|float $b): int|float { return $a + $b; } echo "\nRetorno anulavel (?):\n"; echo " " . describe(null) . "\n"; echo " " . describe(404) . "\n"; echo "\nUnion type (int|float no parametro e no retorno):\n"; echo " somaOuTexto(3, 4) = " . somaOuTexto(3, 4) . " (int)\n"; echo " somaOuTexto(3.5, 4.25) = " . somaOuTexto(3.5, 4.25) . " (float)\n"; // mixed e o tipo que aceita qualquer valor: substitui a falta de tipo. function resumo(mixed $valor): string { return match (true) { is_null($valor) => 'null', is_bool($valor) => 'bool', is_int($valor) => "int ($valor)", is_float($valor) => "float ($valor)", is_string($valor) => "string ($valor)", is_array($valor) => 'array com ' . count($valor) . ' itens', default => 'outro tipo: ' . get_debug_type($valor), }; } echo "\nO tipo mixed passa por qualquer valor:\n"; foreach ([42, 3.14, 'texto', true, null, [1, 2, 3]] as $valor) { echo " " . resumo($valor) . "\n"; } // void: a funcao nao devolve nada. never: ela sempre lanca erro. function registrar(string $mensagem): void { echo " [log] $mensagem\n"; } function validarSenha(string $senha): string { if (strlen($senha) < 8) { throw new InvalidArgumentException('senha precisa de 8 caracteres ou mais'); } return 'senha valida'; } echo "\nvoid apenas executa:\n"; registrar('inicio do relatorio'); echo "never lanca excecao e nunca retorna:\n"; try { validarSenha('123'); } catch (InvalidArgumentException $erro) { echo " InvalidArgumentException: " . $erro->getMessage() . "\n"; } echo " resultado valido: " . validarSenha('senhaforte') . "\n\n"; // O tipo de retorno tambem e conferido: devolver o tipo errado e TypeError. function mediaComErro(array $notas): string { return array_sum($notas) / count($notas); } try { mediaComErro([8.0, 6.0]); } catch (TypeError $erro) { echo "Retorno do tipo errado tambem lanca TypeError:\n " . $erro->getMessage() . "\n"; }
Saída real
somar(10, 5) com dois int: 15 media(7, 5) com int em parametro float: 6 Passando string onde se espera int: TypeError: somar(): Argument #1 ($a) must be of type int, string given, called in /w/aula2.php on line 28 Passando float com parte decimal onde se espera int: TypeError: somar(): Argument #1 ($a) must be of type int, float given, called in /w/aula2.php on line 35 Retorno anulavel (?): sem codigo codigo 404 Union type (int|float no parametro e no retorno): somaOuTexto(3, 4) = 7 (int) somaOuTexto(3.5, 4.25) = 7.75 (float) O tipo mixed passa por qualquer valor: int (42) float (3.14) string (texto) bool null array com 3 itens void apenas executa: [log] inicio do relatorio never lanca excecao e nunca retorna: InvalidArgumentException: senha precisa de 8 caracteres ou mais resultado valido: senha valida Retorno do tipo errado tambem lanca TypeError: mediaComErro(): Return value must be of type string, float returned
Parâmetros especiais
Parâmetros especiais
Além dos parâmetros com tipo, a assinatura aceita valor padrão, nomeação na chamada, quantidade variável de argumentos, tipo anulável e desempacotamento de array. São os recursos que tornam uma função utilizável em código real, sem posição fixa de argumento.
Como se usa
function conectar(string $host, string $user, string $senha, int $porta = 3306, int $timeout = 5): PDO
O valor padrão entra depois dos obrigatórios, nunca antes. O parâmetro com padrão se torna opcional: a chamada pode omiti-lo, e o PHP usa o valor declarado.
Os quatro recursos
| Recurso | Sintaxe | O que faz |
|---|---|---|
| Valor padrão | int $limite = 10 | o argumento pode ser omitido |
| Nomeado | conectar(host: $h, porta: 5432) | argumento pela ordem que você quiser, do PHP 8.0 |
| Variádico | int ...$valores | recebe quantos argumentos houver, num array |
| Spread | f(...$array) | passa um array como se fossem argumentos soltos |
| Anulável | ?int $id | aceita int ou null |
| Promoção | public function __construct(private string $nome) | cria e tipa a propriedade junto, em classe |
Argumento nomeado e variádico juntos resolvem a função de configuração com muitas opções: o que tem nome goes pelo nome, o que sobra cai no variádico.
function log(string $nivel, string $mensagem, ?string $arquivo = null, string ...$extras): void log('erro', 'conexao recusada'); log('erro', 'conexao recusada', arquivo: '/var/log/app.log'); log('info', 'iniciado', null, 'host', 'porta');
A ordem que o PHP exige
Na assinatura, a ordem é rígida: parâmetro obrigatório, depois o com valor padrão, depois o variádico. O variádico tem que ser o último, senão é erro de sintaxe. E a tipagem é uniforme: se um parâmetro declara tipo, todos os outros também declaram, ou a declaração é ignorada.
| Situação | Comportamento |
|---|---|
| Argumento nomeado para parâmetro inexistente | Error: Unknown named parameter |
f($a) com f(int $x, int $y = 2) | $y fica 2 |
f(x: 1) com f(int $x) | funciona, é o parametro nomeado |
| Variádico recebe zero argumento | o array fica vazio, sem erro |
f(...$vazio) | chama f() sem argumento nenhum |
Nomeado não muda o valor padrão:
conectar(porta: 3306)é idêntico aconectar(...)sem o argumento. O que muda é a ordem — dá para chamar a função máxima usando sótimeout: 10, sem repetir os outros. O erro clássico é digitar o nome do parâmetro com maiúscula ou em português: o nome é case-sensitive e tem que ser o da assinatura.
Exemplo
<?php // ============================================================ // AULA 3 - Parametros especiais: padrao, nomeado, variadico, spread // ============================================================ declare(strict_types=1); // --- Valor padrao: o parametro com valor na assinatura vira opcional --- function somar(float $preco, float $quantidade = 1.0, float $desconto = 0.0): float { return ($preco * $quantidade) * (1 - $desconto); } echo "Com todos os argumentos: " . somar(25.90, 3, 0.10) . "\n"; echo "Usando o padrao da qtd: " . somar(25.90) . "\n"; echo "Usando so o desconto: " . somar(25.90, desconto: 0.50) . "\n\n"; // --- Argumento nomeado: a ordem deixa de importar (PHP 8.0) --- function conectar(string $host, string $user, string $senha, int $porta = 3306, int $timeout = 5): string { // A senha nunca aparece na saida: so o nome da variavel entra no log. return "$user@$host:$porta (timeout {$timeout}s, variavel \$senha configurada)"; } echo "Argumento nomeado, fora de ordem:\n"; echo " " . conectar(host: 'localhost', user: 'app', senha: 'oculta', timeout: 10) . "\n"; echo " " . conectar('localhost', 'app', 'oculta', 5432) . " (posicional)\n\n"; // Nome inexistente e erro, e o nome do parametro e case-sensitive. try { conectar(hostname: 'localhost', user: 'app', senha: 'x'); } catch (Error $erro) { echo "Nome de parametro errado: " . $erro->getMessage() . "\n\n"; } // --- Parametro variadico: quantos argumentos vierem, num array --- // A uniao string|int no variadico aceita valores de tipos diferentes, // porque um unico tipo escalar nao daria conta dos dois. function registrar(string $nivel, string $mensagem, string|int ...$extras): string { $detalhe = $extras === [] ? 'sem detalhe' : implode(', ', array_map('strval', $extras)); return "[$nivel] $mensagem ($detalhe)"; } echo "Variadico:\n"; echo " " . registrar('erro', 'conexao recusada') . "\n"; echo " " . registrar('erro', 'conexao recusada', 'tentativa', 3) . "\n"; // Com o variadico, a func nao precisa checar se sobrou argumento: // um array de $extras vazio e o resultado normal de uma chamada sem extras. function somenteExtras(string $fixo, string ...$extras): array { return $extras; } var_dump(somenteExtras('so o fixo')); echo "\n"; // --- Spread: passa um array como se fossem argumentos soltos --- $argumentos = [10.0, 2.0, 0.20]; echo "Spread chamando somar(...): " . somar(...$argumentos) . "\n"; // Com o spread, o array vira os argumentos soltos da chamada, na ordem // em que os parametros foram declarados. str_pad($string, $length, ...). $argumentos = ['PHP', 8, '.']; echo "str_pad(...\$argumentos): " . str_pad(...$argumentos) . "\n"; echo "somar(...[10.0, 2.0]): " . somar(...[10.0, 2.0]) . "\n\n"; // --- Tipo anulavel: aceita o tipo ou null --- function buscar(int|null $id): string { return $id === null ? 'listar todos' : "buscar o id $id"; } echo "Anulavel (?int ou int|null):\n"; echo " " . buscar(null) . "\n"; echo " " . buscar(42) . "\n\n"; // --- Primeiro operando obrigatorio, depois os opcionais, variadico por ultimo --- function montar(string $cabecalho, array $colunas, string $separador = ' | ', bool $cabecalhoEmMaiusculo = true): string { $linha = implode($separador, $colunas); return $cabecalhoEmMaiusculo ? "$linha\n" . str_repeat('-', mb_strlen($linha)) . "\n$linha" : $linha; } echo "Montagem de tabela simples:\n"; echo montar('Tabela', ['id', 'nome', 'nota']) . "\n"; echo "\nCom separador e sem maiuscula:\n"; echo montar('Tabela', ['id', 'nome'], ', ', false) . "\n";
Saída real
Com todos os argumentos: 69.93
Usando o padrao da qtd: 25.9
Usando so o desconto: 12.95
Argumento nomeado, fora de ordem:
app@localhost:3306 (timeout 10s, variavel $senha configurada)
app@localhost:5432 (timeout 5s, variavel $senha configurada) (posicional)
Nome de parametro errado: Unknown named parameter $hostname
Variadico:
[erro] conexao recusada (sem detalhe)
[erro] conexao recusada (tentativa, 3)
array(0) {
}
Spread chamando somar(...): 16
str_pad(...$argumentos): PHP.....
somar(...[10.0, 2.0]): 20
Anulavel (?int ou int|null):
listar todos
buscar o id 42
Montagem de tabela simples:
id | nome | nota
----------------
id | nome | nota
Com separador e sem maiuscula:
id, nome
Passagem por referência e callbacks
Passagem por referência e callbacks
Por padrão, PHP passa argumentos por valor: a função trabalha numa cópia e a variável de quem chamou fica intacta. O & antes do $ inverte isso — a função passa a mexer na variável original. E callable é o tipo que declara que um parâmetro é outra função, o que permite passar comportamento em vez de dado.
Como se usa
function acrescentarTaxa(float &$valor, float $taxa): void { $valor *= (1 + $taxa); } $preco = 100.00; acrescentarTaxa($preco, 0.15); // $preco passa a valer 115.00
O & vai no parâmetro, não na chamada. Na chamada, passa-se a variável normal, e o PHP cuida do resto. Com & no array_pop e no usort, a mesma regra vale.
Por valor contra por referência
| Situação | Comportamento |
|---|---|
function f(int $x) | $x é uma cópia; a variável de fora não muda |
function f(int &$x) | $x é a mesma variável; a de fora muda |
| Objeto passado por valor | a variável é cópia, mas o objeto é o mesmo (objetos são referências) |
f($array) | cópia rasa: os elementos escalares são copiados |
f($array) com objetos dentro | os objetos continuam compartilhados |
unset($parametro) com & | apaga a variável de quem chamou |
A consequência prática: o & só é seguro quando o objetivo é justamente modificar. Função que recebe array só para ler funciona melhor sem &, porque evita que ela altere a lista de quem chamou por acidente.
Callbacks
callable é um tipo como int ou string, e vale para o nome de uma função, uma closure, o nome de um método ('Classe::metodo') ou um array [objeto, 'metodo']. É o tipo do segundo argumento de array_map, array_filter, array_reduce e do comparador de usort.
function aplicar(array $valores, callable $operacao): array { /* ... */ } aplicar([1, 2, 3], 'strval'); aplicar([1, 2, 3], fn (int $n): int => $n ** 2);
| Tipo de callback | Como passar |
|---|---|
| Função interna | 'strtoupper' |
| Função nomeada | 'minhaFuncao' |
| Closure | $closure |
| Arrow function | fn ($v) => $v * 2 |
| Método estático | 'MinhaClasse::processar' |
| Método de objeto | [$objeto, 'processar'] |
Callback que devolve
1ou0no lugar detrue/falsefunciona igual emarray_filter— o PHP converte para booleano. O que quebra é devolver string:'0'é falsy,'1'é truthy, mas'sim'e'nao'também são truthy, então umarray_filterque devolve'não'deixa a linha passar.
Exemplo
<?php // ============================================================ // AULA 4 - Passagem por referencia e callbacks // ============================================================ declare(strict_types=1); // --- Por padrao o PHP passa por VALOR: a funcao trabalha numa copia --- function formatarNome(string $nome): string { $nome = strtoupper($nome); return $nome; } $titulo = 'relatorio mensal'; $resultado = formatarNome($titulo); echo "Por valor: a variavel de fora continua '$titulo', o retorno e '$resultado'\n\n"; // --- Com &, a funcao mexe na variavel original. O & vai no PARAMETRO --- function acrescentarDesconto(float &$valor, float $desconto): void { $valor *= (1 - $desconto); } $preco = 100.00; acrescentarDesconto($preco, 0.15); echo "Por referencia: \$preco agora vale $preco\n"; $outroPreco = 50.00; acrescentarDesconto($outroPreco, 0.50); echo " \$outroPreco agora vale $outroPreco\n\n"; // Funcao com & nao aceita literal nem resultado de expressao: // o argumento tem que ser uma variavel. try { acrescentarDesconto(80.00, 0.10); } catch (Error $erro) { echo "Passar literal para parametro com &: " . $erro->getMessage() . "\n\n"; } // --- Um array passa por valor tambem: a funcao nao altera a lista de fora --- function adicionarItem(array $lista, string $item): array { $lista[] = $item; return $lista; } $original = ['a', 'b']; $comC = adicionarItem($original, 'c'); echo "Array por valor: a original tem " . count($original) . " itens, o retorno tem " . count($comC) . "\n"; echo " conteudo do retorno: " . implode(', ', $comC) . "\n\n"; // --- Callable: o parametro e outra funcao, nao um dado --- function aplicar(array $valores, callable $operacao): array { $saida = []; foreach ($valores as $item) { $saida[] = $operacao($item); } return $saida; } function dobro(int $n): int { return $n * 2; } echo "Callback como funcao interna: " . implode(', ', aplicar([1, 2, 3], 'strval')) . "\n"; echo "Callback como arrow function: " . implode(', ', aplicar([1, 2, 3], fn (int $n): int => $n ** 2)) . "\n"; echo "Callback como funcao nomeada: " . implode(', ', aplicar([5, 6], 'dobro')) . "\n\n"; // --- callable aceita metodo estatico e metodo de objeto --- class Calculadora { public static function quadrado(float $n): float { return (float) ($n ** 2); } public function cubo(float $n): float { return (float) ($n ** 3); } } $calc = new Calculadora(); echo "Metodo estatico: " . implode(', ', aplicar([2, 3], Calculadora::class . '::quadrado')) . "\n"; echo "Metodo de objeto: " . implode(', ', aplicar([2, 3], [$calc, 'cubo'])) . "\n\n"; // --- O proprio PHP usa callable em array_map, array_filter e usort --- $notas = [7.5, 4.0, 9.0, 6.5]; $maiores = array_filter($notas, fn (float $n): bool => $n >= 7.0); usort($maiores, fn (float $a, float $b): int => $b <=> $a); echo "array_filter + usort: " . implode(', ', $maiores) . "\n\n"; // --- O detalhe do array_filter com retorno string --- $linhas = ['a' => 10, 'b' => 0, 'c' => 30]; $porBooleano = array_filter($linhas, fn (int $n): bool => $n > 0); $porTexto = array_filter($linhas, fn (int $n): string => $n > 0 ? 'sim' : 'nao'); echo "Callback devolvendo bool: " . json_encode($porBooleano) . "\n"; echo "Callback devolvendo texto: " . json_encode($porTexto) . " (a string 'nao' e truthy)\n"; echo "No PHP 8 o falsy padrao e null: " . json_encode(array_values(array_filter([0, '', null, 'x'], fn ($v) => $v))) . "\n";
Saída real
Por valor: a variavel de fora continua 'relatorio mensal', o retorno e 'RELATORIO MENSAL'
Por referencia: $preco agora vale 85
$outroPreco agora vale 25
Passar literal para parametro com &: acrescentarDesconto(): Argument #1 ($valor) could not be passed by reference
Array por valor: a original tem 2 itens, o retorno tem 3
conteudo do retorno: a, b, c
Callback como funcao interna: 1, 2, 3
Callback como arrow function: 1, 4, 9
Callback como funcao nomeada: 10, 12
Metodo estatico: 4, 9
Metodo de objeto: 8, 27
array_filter + usort: 9, 7.5
Callback devolvendo bool: {"a":10,"c":30}
Callback devolvendo texto: {"a":10,"b":0,"c":30} (a string 'nao' e truthy)
No PHP 8 o falsy padrao e null: ["x"]