PHP Funções
Uma função é um pedaço de código com um nome, que você escreve uma vez e usa quantas vezes quiser, só chamando o nome. Você já usa funções desde o começo do guia: strlen, count, number_format, print_r… Todas foram escritas por alguém e vêm prontas no PHP. Nesta aula você aprende a criar as suas. É o primeiro passo para organizar programas maiores: em vez de um arquivo enorme, de cima a baixo, você divide o trabalho em partes com nome.
- O que é uma função e por que ela existe.
- A diferença entre funções nativas (do PHP) e as suas.
- Como criar uma função com
functione como chamá-la. - As regras para o nome de uma função (e as convenções).
- Por que dá para chamar uma função antes de escrevê-la no arquivo, e quando isso não funciona.
- Como guardar suas funções num arquivo separado.
Esta é a primeira aula do grupo Funções. As próximas aprofundam cada parte: Parâmetros (os dados que a função recebe) e Tipos e Retorno (o resultado que ela devolve).
A ideia: uma receita com nome
Num caderno de receitas, a receita de "massa de pão" é escrita uma vez. Depois, em outras receitas, basta dizer "faça a massa de pão" (página 12), sem copiar os passos de novo. Se um dia a Ana melhorar a massa, ela muda um lugar, e todas as receitas que usam a massa saem melhores.
Funções são isso: você define (escreve a receita, uma vez) e chama (manda fazer, quantas vezes quiser).
Funções nativas: as que já vêm prontas
O PHP já traz centenas de funções, as funções nativas (ou "internas", built-in). Você chama todas do mesmo jeito: o nome, parênteses, e dentro deles os dados que a função precisa.
<?php
echo strlen("Recife"), "\n";
echo strtoupper("ana"), "\n";
echo count(["a", "b", "c"]), "\n";
echo max(3, 9, 4), "\n";
echo count(get_defined_functions()["internal"]), "\n";
$ php fn-nativas.php 6 « strlen: o tamanho do texto ANA « strtoupper: em maiúsculas 3 « count: quantos itens 9 « max: o maior 1528 « quantas funções nativas este PHP tem
A última linha conta as funções nativas do PHP do laboratório: 1528. O número muda conforme as extensões instaladas, mas a ideia é a mesma: antes de escrever uma função, vale procurar se o PHP já tem uma pronta (o manual do PHP lista todas; as de texto e de arrays estão na Referência de Strings e na Referência de Arrays).
As funções nativas resolvem problemas gerais. As suas resolvem os problemas do seu programa: mostrar o cabeçalho da lojinha, calcular o frete, formatar o preço do jeito da Ana.
O problema: código repetido
A Ana imprime os pedidos da lojinha no terminal, cada um com um cabeçalho:
<?php echo "==============================\n"; echo " Lojinha da Ana - Recife/PE\n"; echo "==============================\n"; echo "Pedido 1: 2 cafés\n"; echo "==============================\n"; echo " Lojinha da Ana - Recife/PE\n"; echo "==============================\n"; echo "Pedido 2: 10 pães\n";
As três linhas do cabeçalho aparecem duas vezes. Com 50 pedidos, seriam 50 cópias. E quando a lojinha mudar de endereço, a Ana vai ter de achar e corrigir cada uma, torcendo para não esquecer nenhuma.
Criar e chamar uma função
<?php
function cabecalho()
{
echo "==============================\n";
echo " Lojinha da Ana - Recife/PE\n";
echo "==============================\n";
}
cabecalho();
echo "Pedido 1: 2 cafés\n";
cabecalho();
echo "Pedido 2: 10 pães\n";
- function
- Palavra reservada que diz "vou definir uma função" (function = função).
- cabecalho
- O nome que você escolheu. É por ele que a função será chamada.
- ( )
- Os parênteses são obrigatórios. Aqui estão vazios porque esta função não precisa de nenhum dado; na próxima seção eles ganham conteúdo.
- { … }
- O corpo da função: as instruções que rodam a cada chamada. A chave de abertura
{na linha de baixo é o estilo recomendado pelo padrão PSR-12 (aula Padrões PSR); na mesma linha também funciona. - cabecalho();
- A chamada: o nome, os parênteses e o ponto e vírgula. É aqui que o código do corpo roda.
$ php fn-cabecalho.php ============================== Lojinha da Ana - Recife/PE ============================== Pedido 1: 2 cafés ============================== Lojinha da Ana - Recife/PE ============================== Pedido 2: 10 pães
A saída é idêntica à do código repetido, mas agora o cabeçalho existe em um lugar só. Mudou o endereço? Uma linha.
Definir não é executar
Escrever a função só a guarda com um nome. O corpo só roda quando alguém chama:
<?php
function saudacao()
{
echo "Olá!\n";
}
echo "Fim\n";
$ php fn-semchamar.php Fim « o "Olá!" não apareceu: ninguém chamou saudacao()
O caminho da execução
Quando o PHP encontra uma chamada, ele "pula" para dentro da função, roda o corpo de cima a baixo e volta para a linha seguinte à chamada:
<?php
function saudacao()
{
echo "Olá! Bem-vinda à lojinha da Ana.\n";
echo "Hoje tem café fresquinho.\n";
}
echo "Antes de chamar\n";
saudacao();
saudacao();
echo "Depois de chamar\n";
$ php fn-primeira.php Antes de chamar Olá! Bem-vinda à lojinha da Ana. « 1ª chamada Hoje tem café fresquinho. Olá! Bem-vinda à lojinha da Ana. « 2ª chamada Hoje tem café fresquinho. Depois de chamar
Crie uma segunda função, rodape(), que mostre Obrigada e volte sempre!, e chame-a depois de cada pedido. Experimente também tirar uma das chamadas e ver o que muda.
<?php
function cabecalho()
{
echo "==============================\n";
echo " Lojinha da Ana - Recife/PE\n";
echo "==============================\n";
}
cabecalho();
echo "Pedido 1: 2 cafés\n";
cabecalho();
echo "Pedido 2: 10 pães\n";
Uma prévia: receber dados e devolver um resultado
A função cabecalho() faz sempre a mesma coisa. As funções ficam bem mais úteis quando recebem dados (entre os parênteses) e devolvem um resultado (com return), como as nativas fazem. Só uma prévia, que as próximas aulas explicam em detalhe:
<?php
function saudacao($nome)
{
echo "Olá, $nome!\n";
}
function dobro($numero)
{
return $numero * 2;
}
saudacao("Bruno");
saudacao("Carla");
$resultado = dobro(21);
echo "O dobro de 21 é $resultado\n";
echo "O dobro de 5 é ", dobro(5), "\n";
$ php fn-param.php Olá, Bruno! Olá, Carla! O dobro de 21 é 42 O dobro de 5 é 10
$nomee$numerosão parâmetros: variáveis que recebem o valor passado na chamada. Veja Parâmetros.returndevolve um valor para quem chamou, que pode guardá-lo numa variável ou usá-lo direto. Veja Tipos e Retorno.
Nomes de funções
As regras
- Começa com uma letra ou
_; depois, letras, números e_. - Sem espaço, hífen ou outros símbolos. Sem o
$(isso é coisa de variável). - Não pode repetir o nome de outra função, nem de uma nativa.
| Nome | Vale? | Por quê |
|---|---|---|
calcularFrete | sim | letras, estilo camelCase |
calcular_frete | sim | letras e _, estilo snake_case |
total2 | sim | número depois da primeira letra |
2vezes | não | começa com número |
mostrar-total | não | hífen (o PHP lê como "menos") |
count | não | já existe uma função nativa com esse nome |
Maiúsculas não importam (mas escreva igual)
Ao contrário das variáveis ($nome e $Nome são diferentes), os nomes de funções não diferenciam maiúsculas de minúsculas:
<?php
function saudacao()
{
echo "Olá!\n";
}
Saudacao();
SAUDACAO();
STRLEN("x");
echo "ok\n";
$ php fn-maiusc.php Olá! Olá! ok « STRLEN também funcionou (sem mostrar nada, porque não tem echo)
Funciona, mas é só uma tolerância antiga do PHP. Escreva sempre do mesmo jeito que na definição: fica mais fácil de achar o nome com a busca do editor.
As convenções
- Use um verbo (a função faz algo):
mostrarCabecalho,calcularFrete,formatarPreco. Para funções que respondem sim/não, é comum começar come/tem(eMaiorDeIdade,temEstoque). - Escolha um estilo e mantenha. As funções nativas usam snake_case (
array_key_exists); muitos projetos modernos usam camelCase (calcularFrete), o mesmo dos métodos das classes (aula Padrões PSR). - Evite acentos. O PHP até aceita
function média(), mas qualquer pessoa que digitemedia()sem acento vai receber um erro. Nomes de código sem acento evitam essa armadilha.
Chamar antes de definir
Até agora, as funções foram escritas no começo do arquivo e chamadas depois. Mas veja isto:
<?php
saudacao();
echo "O dobro de 4 é ", dobro(4), "\n";
function saudacao()
{
echo "Olá! Fui chamada antes de ser escrita.\n";
}
function dobro($n)
{
return $n * 2;
}
$ php fn-antes.php Olá! Fui chamada antes de ser escrita. O dobro de 4 é 8
Funcionou. Isso acontece porque o PHP não executa o arquivo direto: primeiro ele lê o arquivo inteiro e o transforma num formato interno (essa etapa se chama compilação; veja Como o PHP Funciona). Durante a leitura, ele já registra todas as funções escritas "soltas" no arquivo. Quando a execução começa, elas já existem. Em outras linguagens, esse comportamento é chamado de hoisting ("içar": as definições são "puxadas" para o topo).
Quando não funciona: função dentro de um if
Uma função definida dentro de um bloco, como um if, só passa a existir quando a execução chega naquela linha:
<?php
saudacao();
$modoFesta = true;
if ($modoFesta) {
function saudacao()
{
echo "Olá! Hoje é dia de festa!\n";
}
}
$ php fn-condicional2.php
Fatal error: Uncaught Error: Call to undefined function saudacao() in /home/ana/site/fn-condicional2.php:2
Stack trace:
#0 {main}
thrown in /home/ana/site/fn-condicional2.php on line 2
Com a chamada depois do if, o mesmo código funciona (Olá! Hoje é dia de festa!). Funções condicionais existem, mas são raras; quase sempre há um jeito mais claro.
Nem com funções de outro arquivo
Funções que estão em outro arquivo só existem depois que esse arquivo é carregado com require. A seção seguinte mostra isso.
Mesmo podendo chamar antes, a convenção é definir primeiro e usar depois: funções no começo do arquivo (ou num arquivo separado), o "programa principal" no fim. Quem lê o código de cima para baixo entende melhor.
Organizar: um arquivo só para as funções
Quando o programa cresce, a Ana separa as funções num arquivo próprio, funcoes.php, e o carrega no começo de cada página com require_once ("exija, uma vez só"). Assim, todas as páginas da lojinha usam o mesmo cabeçalho.
<?php
function cabecalho()
{
echo "==============================\n";
echo " Lojinha da Ana - Recife/PE\n";
echo "==============================\n";
}
function rodape()
{
echo "------------------------------\n";
echo "Obrigada e volte sempre!\n";
}
<?php require_once "funcoes.php"; cabecalho(); echo "Pedido 1: 2 cafés\n"; rodape();
$ php loja.php ============================== Lojinha da Ana - Recife/PE ============================== Pedido 1: 2 cafés ------------------------------ Obrigada e volte sempre!
Aqui a ordem importa: se a chamada vier antes do require_once, as funções ainda não foram carregadas.
<?php cabecalho(); require_once "funcoes.php";
$ php loja2.php
Fatal error: Uncaught Error: Call to undefined function cabecalho() in /home/ana/site/loja2.php:2
Stack trace:
#0 {main}
thrown in /home/ana/site/loja2.php on line 2
O require e seus irmãos (include, require_once, include_once) são o assunto da aula include e require. Por que _once? Porque carregar o mesmo arquivo de funções duas vezes daria o erro Cannot redeclare function, que você vê logo abaixo.
Este exemplo tem dois arquivos (veja as abas). O loja.php é o que roda; ele carrega o funcoes.php. Acrescente uma função nova no funcoes.php (por exemplo, horario(), que mostre o horário de funcionamento) e chame-a no loja.php.
<?php require_once "funcoes.php"; cabecalho(); echo "Pedido 1: 2 cafés\n"; rodape();
<?php
function cabecalho()
{
echo "==============================\n";
echo " Lojinha da Ana - Recife/PE\n";
echo "==============================\n";
}
function rodape()
{
echo "------------------------------\n";
echo "Obrigada e volte sempre!\n";
}
Antes de criar, pergunte se já existe
A função function_exists diz se uma função existe (sua ou nativa). É útil para conferir se o PHP instalado tem uma função nova:
<?php
function saudacao()
{
}
var_dump(function_exists("saudacao"));
var_dump(function_exists("strlen"));
var_dump(function_exists("array_first"));
var_dump(function_exists("voar"));
$ php fn-exists.php bool(true) bool(true) bool(true) « array_first existe: este é o PHP 8.5 bool(false)
Quando dá errado
Call to undefined function saudacoa()
<?php
function saudacao()
{
echo "Olá!\n";
}
saudacoa();
$ php fn-undefined.php
Fatal error: Uncaught Error: Call to undefined function saudacoa() in /home/ana/site/fn-undefined.php:6
Stack trace:
#0 {main}
thrown in /home/ana/site/fn-undefined.php on line 6
O que aconteceu: "chamada a uma função não definida". O PHP não conhece nenhuma função com esse nome. As causas mais comuns: erro de digitação (como aqui, saudacoa); o arquivo com a função não foi carregado (ou foi carregado depois da chamada); a função está dentro de um if que ainda não rodou; ou é uma função nativa de uma extensão que não está instalada, ou de uma versão mais nova do PHP.
Como resolver: copie o nome da definição e cole na chamada. Confira o require. Para funções nativas, veja o manual (ele diz a versão e a extensão) e use function_exists.
Cannot redeclare function saudacao()
<?php
function saudacao()
{
echo "Olá!\n";
}
function saudacao()
{
echo "Oi!\n";
}
$ php fn-redeclare.php
Fatal error: Cannot redeclare function saudacao() (previously declared in /home/ana/site/fn-redeclare.php:2) in /home/ana/site/fn-redeclare.php on line 6
Stack trace:
#0 {main}
O que aconteceu: "não é possível declarar de novo". Duas funções com o mesmo nome. A mensagem diz onde está a primeira (previously declared in… linha 2) e onde está a repetida (linha 6). Também acontece quando o mesmo arquivo de funções é carregado duas vezes com require/include (por isso o require_once).
Com o nome de uma função nativa, a mensagem é parecida, sem o "previously declared":
$ php fn-nativa-nome.php
Fatal error: Cannot redeclare function count() in /home/ana/site/fn-nativa-nome.php on line 2
Stack trace:
#0 {main}
Como resolver: dê outro nome a uma das funções (e lembre que maiúsculas não contam: Count também colide). Para arquivos de funções, use require_once.
Parse error: syntax error, unexpected token "-", expecting "("
<?php
function mostrar-total()
{
}
$ php fn-hifen.php
Parse error: syntax error, unexpected token "-", expecting "(" in /home/ana/site/fn-hifen.php on line 2
O que aconteceu: o PHP leu o nome mostrar e esperava os parênteses; achou um hífen. Com um nome que começa com número (function 2vezes()), a mensagem é unexpected integer "2", expecting "(".
Como resolver: use só letras, números (não no começo) e _: mostrarTotal ou mostrar_total.
Referência rápida
| Você quer… | Código |
|---|---|
| Definir uma função | function nome() { … } |
| Chamar | nome(); |
| Receber um dado | function saudacao($nome) { … } → saudacao("Ana"); |
| Devolver um resultado | function dobro($n) { return $n * 2; } → $x = dobro(4); |
| Carregar funções de outro arquivo | require_once "funcoes.php"; |
| Saber se uma função existe | function_exists("nome") |
Missão final
Missão: a nota da lojinha repete a mesma linha de traços três vezes. Crie uma função linha() que mostre os traços e troque os três echo repetidos por chamadas a ela. A saída deve continuar igual.
<?php echo "--------------------\n"; echo "Café ........ 18,90\n"; echo "--------------------\n"; echo "Pão .......... 0,75\n"; echo "--------------------\n";
<?php
function linha()
{
echo "--------------------\n";
}
linha();
echo "Café ........ 18,90\n";
linha();
echo "Pão .......... 0,75\n";
linha();
$ php nota.php -------------------- Café ........ 18,90 -------------------- Pão .......... 0,75 --------------------
Exercícios
1. A palavra que define
Complete para definir a função boasVindas:
{
echo "Bem-vinda!\n";
}
2. A chamada
Complete para chamar a função boasVindas:
3. Qual destes nomes de função é inválido?
4. Um arquivo chama ola(); na linha 2 e define function ola() { … } na linha 5, solta no arquivo. O que acontece?
5. Um arquivo só tem a definição function ola() { echo "Olá"; }, sem nenhuma chamada. O que ele mostra ao rodar?
Resumo
- Uma função é um bloco de código com nome: definida uma vez, chamada quantas vezes quiser. Evita repetição e deixa mudanças num lugar só.
- O PHP tem mais de mil funções nativas; as suas resolvem os problemas do seu programa.
- Defina com
function nome() { … }; chame comnome();. Definir não executa nada. - Nomes: letra ou
_no começo, sem hífen, sem repetir outra função. Maiúsculas não importam, mas escreva igual. - Funções soltas no arquivo podem ser chamadas antes da definição; dentro de
ifou em outro arquivo, só depois. - Guarde as funções num arquivo e carregue com
require_once.