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.

Você vai aprender
  • 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 function e 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
  • $nome e $numero são parâmetros: variáveis que recebem o valor passado na chamada. Veja Parâmetros.
  • return devolve 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.
NomeVale?Por quê
calcularFretesimletras, estilo camelCase
calcular_fretesimletras e _, estilo snake_case
total2simnúmero depois da primeira letra
2vezesnãocomeça com número
mostrar-totalnãohífen (o PHP lê como "menos")
countnãojá 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 com e/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 digite media() 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.

Onde colocar, então?

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çãofunction nome() { … }
Chamarnome();
Receber um dadofunction saudacao($nome) { … } → saudacao("Ana");
Devolver um resultadofunction dobro($n) { return $n * 2; } → $x = dobro(4);
Carregar funções de outro arquivorequire_once "funcoes.php";
Saber se uma função existefunction_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:

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 com nome();. 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 if ou em outro arquivo, só depois.
  • Guarde as funções num arquivo e carregue com require_once.