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.

Você vai aprender
  • 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 o return.

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.

TermoOnde apareceExemplo
ParâmetroNa definição da função: a variável que vai receber o dadofunction saudacao($nome)
ArgumentoNa chamada: o valor que você entregasaudacao("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 &amp; Jerry", double_encode: false), "\n";
echo htmlspecialchars("Tom &amp; 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 &amp; Jerry          « double_encode: false — pulou 2 opcionais para chegar ao 4º
Tom &amp;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).

O nome do parâmetro vira parte do "contrato"

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 recebeuma cópiaa própria variável
Mudanças dentro afetam fora?nãosim
Aceita valor solto (f(10))?simnão (erro)
Quando usarquase sempre, com returnquando mudar a variável é o objetivo
E os objetos?

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).

A função "não mudou" a minha variável

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âmetrofunction f($x) { … } → f(10);
Váriosfunction f($x, $y) { … } → f(10, 20);
Opcional, com padrãofunction f($x, $y = 1) { … } → f(10);
Padrão calculadofunction f($quando = null) { $quando = $quando ?? date("d/m/Y"); }
Argumento nomeadof(10, y: 5), f(y: 5, x: 10)
Pular opcionais do meiohtmlspecialchars($t, double_encode: false)
Mudar a variável de quem chamafunction 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:

function saudar($nome, $saudacao ) { … }

2. Só o desconto

Complete a chamada para passar só o desconto de 20%, usando argumento nomeado:

precoFinal(50, );

3. Mudar o original

Complete para a função mudar a variável de quem chama:

function zerar() { $x = 0; }

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 (use null + ?? 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. Prefira return.