PHP Parâmetros
Na aula Funções, você criou funções que faziam sempre a mesma coisa. Uma função fica muito mais útil quando você pode entregar dados a ela na hora da chamada: o nome do cliente, o preço, a quantidade. Esses dados chegam por meio dos parâmetros. Esta aula mostra como declarar parâmetros, como deixá-los opcionais com valores padrão, como chamar a função dizendo o nome de cada um (argumentos nomeados, do PHP 8.0) e a diferença entre passar uma cópia e passar a própria variável.
- A diferença entre parâmetro e argumento.
- Funções com vários parâmetros, e por que a ordem importa.
- O que acontece com argumentos a menos (
ArgumentCountError) e a mais. - Valores padrão:
function f($x, $y = 10). - Argumentos nomeados:
precoFinal(18.9, desconto: 0.1). - Passagem por valor × por referência (
&$x), e por que preferir oreturn.
A ideia: os campos de um formulário
Pense num formulário de pedido em papel: ele tem campos Produto, Quantidade, Desconto. O formulário (a função) é sempre o mesmo; o que muda é o que cada cliente preenche nos campos. Os campos são os parâmetros; o que é preenchido em cada pedido são os argumentos.
| Termo | Onde aparece | Exemplo |
|---|---|---|
| Parâmetro | Na definição da função: a variável que vai receber o dado | function saudacao($nome) |
| Argumento | Na chamada: o valor que você entrega | saudacao("Ana") |
Na prática, muita gente fala "parâmetro" para os dois, e tudo bem. Mas as mensagens de erro do PHP usam as duas palavras com precisão (Too few arguments, Unknown named parameter), então vale saber a diferença.
Um parâmetro
<?php
function saudacao($nome)
{
echo "Olá, $nome!\n";
}
saudacao("Ana");
saudacao("Bruno");
$cliente = "Carla";
saudacao($cliente);
saudacao("Dona " . $cliente);
- function saudacao($nome)
- Entre os parênteses, o parâmetro: uma variável comum, com
$. Ela só existe dentro da função (aula Escopo). - saudacao("Ana");
- Na chamada, o argumento
"Ana"é copiado para$nome, e o corpo roda. - saudacao($cliente);
- O argumento pode ser uma variável: o valor dela (
"Carla") é que vai para$nome. Os nomes não precisam combinar. - saudacao("Dona " . $cliente);
- Ou qualquer expressão: o PHP calcula primeiro (
"Dona Carla") e depois chama.
$ php p-um.php Olá, Ana! Olá, Bruno! Olá, Carla! Olá, Dona Carla!
Vários parâmetros: a ordem manda
Separe os parâmetros com vírgulas. Na chamada, os argumentos são entregues na mesma ordem: o primeiro argumento vai para o primeiro parâmetro, e assim por diante.
<?php
function precoFinal($preco, $quantidade, $desconto)
{
$total = $preco * $quantidade;
return $total - $total * $desconto;
}
echo precoFinal(18.9, 2, 0.1), "\n";
echo precoFinal(2, 0.1, 18.9), "\n";
$ php p-varios.php 34.02 « 2 cafés de 18,90 com 10% de desconto -3.58 « mesma função, argumentos fora de ordem: resultado sem sentido
Na segunda chamada, o PHP não reclamou: ele colocou 2 em $preco, 0.1 em $quantidade e 18.9 em $desconto, exatamente como mandado. O PHP não tem como saber o que você quis dizer. Os argumentos nomeados, mais abaixo, resolvem esse problema.
Argumentos a menos: ArgumentCountError
<?php
function precoFinal($preco, $quantidade, $desconto)
{
$total = $preco * $quantidade;
return $total - $total * $desconto;
}
echo precoFinal(18.9, 2), "\n";
$ php p-poucos.php
Fatal error: Uncaught ArgumentCountError: Too few arguments to function precoFinal(), 2 passed in /home/ana/site/p-poucos.php on line 8 and exactly 3 expected in /home/ana/site/p-poucos.php:2
Stack trace:
#0 /home/ana/site/p-poucos.php(8): precoFinal(18.9, 2)
#1 {main}
thrown in /home/ana/site/p-poucos.php on line 2
Leia a mensagem com calma, que ela diz tudo:
- ArgumentCountError
- "Erro na contagem de argumentos": o tipo do erro.
- Too few arguments to function precoFinal()
- "Argumentos de menos para a função
precoFinal()". - 2 passed in … on line 8
- Foram passados 2, na chamada da linha 8.
- and exactly 3 expected
- E eram esperados exatamente 3.
- in …/p-poucos.php:2
- A linha 2 é onde a função foi definida.
- #0 …(8): precoFinal(18.9, 2)
- O stack trace mostra a chamada que deu errado, com os valores.
O erro é fatal: o programa para ali. Em geral, o lugar a corrigir é a chamada (linha 8), não a função.
Argumentos a mais
<?php
function saudacao($nome)
{
echo "Olá, $nome!\n";
}
saudacao("Ana", "Bruno", 42);
echo strlen("Ana", "Bruno");
$ php p-muitos.php
Olá, Ana! « nas suas funções: os argumentos extras são ignorados, sem aviso
Fatal error: Uncaught ArgumentCountError: strlen() expects exactly 1 argument, 2 given in /home/ana/site/p-muitos.php:7
Stack trace:
#0 /home/ana/site/p-muitos.php(7): strlen('Ana', 'Bruno')
#1 {main}
thrown in /home/ana/site/p-muitos.php on line 7
Uma diferença curiosa: as funções que você escreve aceitam argumentos sobrando em silêncio (eles podem ser lidos com func_get_args, veja Funções Variádicas); as nativas são rigorosas e param o programa.
Valores padrão: parâmetros opcionais
Na maioria das compras, a quantidade é 1 e não há desconto. Em vez de obrigar quem chama a escrever precoFinal(18.9, 1, 0.0) toda vez, dê a esses parâmetros um valor padrão com =. Se o argumento não vier, vale o padrão.
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
$total = $preco * $quantidade;
return $total - $total * $desconto;
}
echo precoFinal(18.9), "\n";
echo precoFinal(18.9, 3), "\n";
echo precoFinal(18.9, 3, 0.1), "\n";
$ php p-padrao.php 18.9 « só o preço: quantidade 1, sem desconto 56.7 « preço e quantidade 51.03 « os três
Agora $preco é obrigatório e os outros dois são opcionais. Você já usa isso com funções nativas: o number_format funciona com 1, 2 ou 4 argumentos, e in_array tem o terceiro argumento opcional (o modo estrito).
Chame precoFinal de outras formas: só com o preço, com quantidade, com desconto. Depois mude o valor padrão da quantidade para 2 e veja quais resultados mudam.
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
$total = $preco * $quantidade;
return $total - $total * $desconto;
}
echo precoFinal(18.9), "\n";
echo precoFinal(18.9, 3), "\n";
echo precoFinal(18.9, desconto: 0.1), "\n";
Regra 1: os opcionais vão no fim
Com argumentos por posição, não dá para "pular" um parâmetro do meio. Por isso, os parâmetros com valor padrão devem ficar depois dos obrigatórios. Se ficarem antes, o padrão não serve para nada, e o PHP avisa:
<?php
function saudacao($saudacao = "Olá", $nome)
{
echo "$saudacao, $nome!\n";
}
saudacao("Oi", "Ana");
saudacao("Ana");
$ php p-ordem.php
Deprecated: saudacao(): Optional parameter $saudacao declared before required parameter $nome is implicitly treated as a required parameter in /home/ana/site/p-ordem.php on line 2
Oi, Ana!
Fatal error: Uncaught ArgumentCountError: Too few arguments to function saudacao(), 1 passed in /home/ana/site/p-ordem.php on line 7 and exactly 2 expected in /home/ana/site/p-ordem.php:2
Stack trace:
#0 /home/ana/site/p-ordem.php(7): saudacao('Ana')
#1 {main}
thrown in /home/ana/site/p-ordem.php on line 2
O aviso diz: "o parâmetro opcional $saudacao, declarado antes do obrigatório $nome, é tratado como obrigatório". Ou seja, o = "Olá" foi ignorado. A correção é inverter: function saudacao($nome, $saudacao = "Olá").
Regra 2: o padrão precisa ser um valor fixo
O valor padrão tem de ser conhecido antes de o programa rodar: um número, um texto, true/false, null, um array, uma constante. Chamar uma função ali não pode:
<?php
function registrar($mensagem, $quando = date("d/m/Y"))
{
echo "[$quando] $mensagem\n";
}
$ php p-constexpr.php
Fatal error: Constant expression contains invalid operations in /home/ana/site/p-constexpr.php on line 2
Stack trace:
#0 {main}
"A expressão constante contém operações inválidas." O truque padrão é usar null como padrão e calcular o valor de verdade dentro da função, com o ?? (aula ?? e ?->):
<?php
function registrar($mensagem, $quando = null)
{
$quando = $quando ?? date("d/m/Y");
echo "[$quando] $mensagem\n";
}
registrar("Pedido recebido", "01/10/2026");
registrar("Loja aberta");
$ php p-null.php [01/10/2026] Pedido recebido [17/10/2026] Loja aberta « sem o 2º argumento: a data do dia em que o programa rodou
Argumentos nomeados PHP 8.0+
E se a Ana quiser dar desconto, mas manter a quantidade padrão? Com argumentos por posição, ela teria de repetir o padrão: precoFinal(18.9, 1, 0.1). Desde o PHP 8.0, dá para dizer o nome do parâmetro na chamada, e pular os que não interessam:
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
$total = $preco * $quantidade;
return $total - $total * $desconto;
}
echo precoFinal(18.9, 1, 0.1), "\n";
echo precoFinal(18.9, desconto: 0.1), "\n";
echo precoFinal(preco: 18.9, quantidade: 2), "\n";
echo precoFinal(desconto: 0.5, preco: 10, quantidade: 3), "\n";
- desconto: 0.1
- O nome do parâmetro sem o
$, dois-pontos e o valor. Lê-se "desconto vale 0.1". - precoFinal(18.9, desconto: 0.1)
- Mistura: o primeiro por posição (vai para
$preco), o outro pelo nome. A$quantidade, que ficou de fora, usa o padrão. - precoFinal(desconto: 0.5, preco: 10, quantidade: 3)
- Com todos nomeados, a ordem é livre.
$ php p-nomeados.php 17.01 17.01 « o mesmo resultado, sem repetir o padrão da quantidade 37.8 15 « 10 × 3, com 50% de desconto
Além de pular opcionais, os nomes deixam a chamada autoexplicativa. Compare precoFinal(10, 3, 0.5) com precoFinal(preco: 10, quantidade: 3, desconto: 0.5): no segundo, ninguém precisa abrir a definição para entender.
Também nas funções nativas
Os nomes dos parâmetros das funções nativas são os que aparecem no manual do PHP. Isso ajuda muito nas funções com muitos opcionais:
<?php
echo number_format(1234.5, 2, ",", "."), "\n";
echo number_format(1234.5, decimals: 2, decimal_separator: ",", thousands_separator: "."), "\n";
echo str_pad("7", 3, "0", STR_PAD_LEFT), "\n";
echo str_pad("7", length: 3, pad_string: "0", pad_type: STR_PAD_LEFT), "\n";
echo htmlspecialchars("Tom & Jerry", double_encode: false), "\n";
echo htmlspecialchars("Tom & Jerry"), "\n";
$ php p-nativa.php 1.234,50 1.234,50 « a mesma coisa, mas dá para ler o que é cada argumento 007 007 Tom & Jerry « double_encode: false — pulou 2 opcionais para chegar ao 4º Tom &amp; Jerry
Na última dupla, double_encode é o quarto parâmetro do htmlspecialchars. Sem o nome, seria preciso escrever os dois do meio com os seus padrões. (O que ele faz: não codificar de novo o que já está codificado; veja Escapar a Saída.)
As regras dos nomeados
- Os posicionais vêm primeiro, os nomeados depois. Nunca o contrário.
- O nome tem de existir na função (sem erro de digitação).
- Cada parâmetro recebe um valor uma vez só.
- Os obrigatórios continuam obrigatórios, venham por posição ou por nome.
Cada regra quebrada tem a sua mensagem (veja Quando dá errado).
Sem argumentos nomeados, você podia renomear $desconto para $percentual à vontade. Agora, se alguém chamou precoFinal(…, desconto: 0.1), renomear quebra essa chamada (Unknown named parameter $desconto). Escolha bons nomes desde o começo.
Por valor × por referência
Por valor: a função recebe uma cópia
Normalmente, o parâmetro recebe uma cópia do valor. Mudar o parâmetro dentro da função não muda nada fora dela. É como entregar uma fotocópia de um documento: rabiscar a cópia não estraga o original.
<?php
function aumentar($numero)
{
$numero = $numero + 1;
echo "Dentro da função: $numero\n";
}
$estoque = 10;
aumentar($estoque);
echo "Fora da função: $estoque\n";
$ php p-valor.php Dentro da função: 11 Fora da função: 10 « $estoque não mudou
Com arrays é igual: a função recebe uma cópia do array.
<?php
function adicionarItem($lista, $item)
{
$lista[] = $item;
echo "Dentro: ", implode(", ", $lista), "\n";
}
$compras = ["arroz", "feijão"];
adicionarItem($compras, "café");
echo "Fora: ", implode(", ", $compras), "\n";
$ php p-valor-array.php Dentro: arroz, feijão, café Fora: arroz, feijão « a lista original continua com 2 itens
Isso é uma proteção: você pode chamar qualquer função sem medo de que ela estrague suas variáveis.
Por referência: & entrega a própria variável
Colocando & antes do parâmetro, a função recebe a própria variável (o original, não uma cópia). O que ela mudar, muda lá fora.
<?php
function aumentar(&$numero)
{
$numero = $numero + 1;
}
function adicionarItem(&$lista, $item)
{
$lista[] = $item;
}
$estoque = 10;
aumentar($estoque);
aumentar($estoque);
echo "Estoque: $estoque\n";
$compras = ["arroz", "feijão"];
adicionarItem($compras, "café");
echo implode(", ", $compras), "\n";
$ php p-ref.php Estoque: 12 « duas chamadas, dois aumentos no original arroz, feijão, café
O & vai só na definição; a chamada é normal. É exatamente assim que funcionam sort, array_push e array_pop, que mudam o array que você passa (aulas Ordenar Arrays e Funções de Array). E é por isso que elas exigem uma variável: um valor solto não tem onde guardar a mudança.
<?php
function aumentar(&$numero)
{
$numero = $numero + 1;
}
aumentar(10);
$ php p-ref-literal.php
Fatal error: Uncaught Error: aumentar(): Argument #1 ($numero) could not be passed by reference in /home/ana/site/p-ref-literal.php:6
Stack trace:
#0 {main}
thrown in /home/ana/site/p-ref-literal.php on line 6
Qual usar?
Prefira por valor + return. A função devolve o resultado, e quem chama decide onde guardar:
<?php
function comItem($lista, $item)
{
$lista[] = $item;
return $lista;
}
$compras = ["arroz", "feijão"];
$compras = comItem($compras, "café");
echo implode(", ", $compras), "\n";
$ php p-return.php arroz, feijão, café
Lendo $compras = comItem(…), qualquer pessoa vê que $compras muda. Lendo adicionarItem($compras, …), só olhando a definição dá para saber. Use referência quando a função realmente existe para mudar a variável (como o sort) ou para devolver mais de um resultado.
Por valor ($x) | Por referência (&$x) | |
|---|---|---|
| A função recebe | uma cópia | a própria variável |
| Mudanças dentro afetam fora? | não | sim |
Aceita valor solto (f(10))? | sim | não (erro) |
| Quando usar | quase sempre, com return | quando mudar a variável é o objetivo |
Objetos (Nível 3) se comportam de um jeito diferente: a função recebe uma "cópia do endereço" do objeto, e consegue mudar as propriedades dele mesmo sem &. Isso é explicado em Classes e Objetos.
Quando dá errado
ArgumentCountError: Too few arguments to function …
O que aconteceu: a chamada passou menos argumentos que os parâmetros obrigatórios. Veja a saída de p-poucos.php, mais acima: a mensagem diz quantos foram passados, quantos eram esperados e a linha da chamada.
Como resolver: complete a chamada; ou, se o dado é mesmo opcional, dê um valor padrão ao parâmetro (no fim da lista).
Cannot use positional argument after named argument
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
return $preco * $quantidade * (1 - $desconto);
}
echo precoFinal(preco: 18.9, 2);
$ php p-err-pos.php
Fatal error: Cannot use positional argument after named argument in /home/ana/site/p-err-pos.php on line 6
Stack trace:
#0 {main}
O que aconteceu: depois de um argumento nomeado, veio um por posição. O PHP não saberia em que posição colocar o 2.
Como resolver: posicionais primeiro (precoFinal(18.9, 2)) ou todos nomeados (precoFinal(preco: 18.9, quantidade: 2)).
Unknown named parameter $desconta
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
return $preco * $quantidade * (1 - $desconto);
}
echo precoFinal(18.9, desconta: 0.1);
$ php p-err-desconhecido.php
Fatal error: Uncaught Error: Unknown named parameter $desconta in /home/ana/site/p-err-desconhecido.php:6
Stack trace:
#0 {main}
thrown in /home/ana/site/p-err-desconhecido.php on line 6
O que aconteceu: "parâmetro nomeado desconhecido". Não existe $desconta (é $desconto). Para funções nativas, confira o nome exato no manual.
Named parameter $preco overwrites previous argument
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
return $preco * $quantidade * (1 - $desconto);
}
echo precoFinal(18.9, preco: 20);
$ php p-err-dupl.php
Fatal error: Uncaught Error: Named parameter $preco overwrites previous argument in /home/ana/site/p-err-dupl.php:6
Stack trace:
#0 {main}
thrown in /home/ana/site/p-err-dupl.php on line 6
O que aconteceu: o 18.9 já foi para $preco pela posição, e depois veio preco: 20. Um parâmetro, dois valores.
Como resolver: passe cada parâmetro uma vez só.
ArgumentCountError: precoFinal(): Argument #1 ($preco) not passed
<?php
function precoFinal($preco, $quantidade = 1, $desconto = 0.0)
{
return $preco * $quantidade * (1 - $desconto);
}
echo precoFinal(desconto: 0.1);
$ php p-err-faltanome.php
Fatal error: Uncaught ArgumentCountError: precoFinal(): Argument #1 ($preco) not passed in /home/ana/site/p-err-faltanome.php:2
Stack trace:
#0 /home/ana/site/p-err-faltanome.php(6): precoFinal(NULL, NULL, 0.1)
#1 {main}
thrown in /home/ana/site/p-err-faltanome.php on line 2
O que aconteceu: com argumentos nomeados, um obrigatório ficou de fora. A mensagem é diferente do "Too few arguments": ela diz qual parâmetro faltou (o nº 1, $preco).
Como resolver: precoFinal(18.9, desconto: 0.1).
O que aconteceu: o parâmetro é por valor (o normal), então a função mexeu numa cópia. Veja p-valor.php.
Como resolver: faça a função devolver o novo valor com return e guarde: $estoque = aumentar($estoque);. Ou, se for mesmo o caso, use & no parâmetro.
Referência rápida
| Você quer… | Código |
|---|---|
| Um parâmetro | function f($x) { … } → f(10); |
| Vários | function f($x, $y) { … } → f(10, 20); |
| Opcional, com padrão | function f($x, $y = 1) { … } → f(10); |
| Padrão calculado | function f($quando = null) { $quando = $quando ?? date("d/m/Y"); } |
| Argumento nomeado | f(10, y: 5), f(y: 5, x: 10) |
| Pular opcionais do meio | htmlspecialchars($t, double_encode: false) |
| Mudar a variável de quem chama | function f(&$x) { $x++; } → f($n); |
| Devolver o novo valor (preferível) | function f($x) { return $x + 1; } → $n = f($n); |
Parâmetros também podem ter tipo (function f(int $x)): é a próxima aula, Tipos e Retorno. E uma função pode receber quantos argumentos quiser (function soma(...$numeros)): veja Funções Variádicas.
Missão final
Missão: o programa para com ArgumentCountError. Dê valores padrão aos parâmetros da função ($moeda = "R$" e $casas = 2), para as duas primeiras chamadas funcionarem como estão. Depois, troque a terceira chamada por uma com argumento nomeado, casas: 0, sem repetir o "R$". A saída deve ser R$ 18,90, US$ 1.234,50 e R$ 19.
<?php
function formatarPreco($valor, $moeda, $casas)
{
return $moeda . " " . number_format($valor, $casas, ",", ".");
}
echo formatarPreco(18.9), "\n";
echo formatarPreco(1234.5, "US$"), "\n";
echo formatarPreco(18.9, "R$", 0), "\n";
<?php
function formatarPreco($valor, $moeda = "R$", $casas = 2)
{
return $moeda . " " . number_format($valor, $casas, ",", ".");
}
echo formatarPreco(18.9), "\n";
echo formatarPreco(1234.5, "US$"), "\n";
echo formatarPreco(18.9, casas: 0), "\n";
$ php precos.php R$ 18,90 US$ 1.234,50 R$ 19 « number_format com 0 casas arredonda 18,9 para 19
Exercícios
1. Valor padrão
Complete para o parâmetro $saudacao valer "Olá" quando não for passado:
2. Só o desconto
Complete a chamada para passar só o desconto de 20%, usando argumento nomeado:
3. Mudar o original
Complete para a função mudar a variável de quem chama:
4. Com function f($a, $b = 2, $c = 3), qual chamada dá ArgumentCountError?
5. O que este código mostra? function dobrar($n) { $n = $n * 2; } $x = 5; dobrar($x); echo $x;
6. Qual chamada é inválida?
Resumo
- Parâmetros são as variáveis da definição; argumentos, os valores da chamada. Por posição, a ordem manda.
- Argumentos a menos:
ArgumentCountError: Too few arguments. A mais: ignorados nas suas funções, erro nas nativas. - Valor padrão (
$y = 1) torna o parâmetro opcional; opcionais vão no fim, e o padrão deve ser um valor fixo (usenull+??para calcular). - Argumentos nomeados (PHP 8.0):
f(10, desconto: 0.1). Pulam opcionais e explicam a chamada. Posicionais primeiro. - Por valor (o normal), a função mexe numa cópia; por referência (
&$x), no original. Prefirareturn.