# PHP para Iniciantes: Funções - Definidas pelo Usuário

Até aqui, já vimos uma série de exemplos sobre funções na prática, desde a criação até a usabilidade de uma, mas nada oficial como material de estudo, apenas como exemplo do assunto que estávamos falando na hora. Dito isso, precisamos dar dez passos para trás para mostrar o que exatamente é uma função definida pelo usuário...

> Peraí... **Quem é esse usuário**, Kiko?

**Você**, ué. O usuário da compilação é quem escreveu o código a ser compilado. Então se você escreveu uma função no código, essa função é chamada **função definida pelo usuário**, afinal, como vimos no artigo anterior, já temos as **funções internas**.

Além disso, essas **funções definidas** também são conhecidas como **funções nomeadas**, onde obrigatoriamente cada função deve ter um nome único. As regras de escrita de uma função são as mesmas de uma variável, exceto que não colocamos o operador de variável na frente (`$`). Ou seja, o primeiro caractere deve ser uma letra ou um *underline* (`_`) e as demais podem ser, também, números.

No caso de funções, as letras são **case insensitive**, portanto, não importa a forma que você as escreva (tudo maiúsculo, tudo minúsculo, tudo bagunçado), desde que tenha as mesmas letras na mesma sequência, a função será chamada. Mesmo assim, é bom senso escrever exatamente do mesmíssimo jeito que definiu no momento da declaração, beleza?

**Reforçando**: funções nomeadas são **constantes**, isto é, você não pode redefini-la. No máximo criar outra com outro nome. Mesmo variando o maiúsculo e/ou minúsculo, como a declaração é **case insensitive**, ainda daria conflito.

E mais uma observação: as funções não são declaradas no momento da **evaluação** (leia-se interpretação com dados de entrada) do código e sim na compilação, ou seja, você pode chamar a função antes de definí-la, desde que ela realmente seja definida posteriormente sem nenhuma dependência da interpretação de uma expressão.

**Além disso tudo** tem outro ponto importantíssimo: **toda função nomeada tem contexto GLOBAL**. Mesmo que você a crie dentro de mil laços, ela ainda vai ser acessível do lado de fora de todos eles. Da mesma forma, você não vai conseguir declarar a função mais de uma vez.

E aqui acabamos com os ***litle details*** hehehehehehehehe.
<center> ![Hehehehe](https://media.giphy.com/media/BYul6RujgoRCryuCdL/giphy.gif) </center>

Calma, não se desespere, é claro que eu vou colocar tudo o que falei em prática. Vamos revisar cada ponto mencionado em forma de exemplos:

## 1 - Uma função deve ter um nome único

Considere o seguinte arquivo, responsável por definir a função `nomeUnico()`:

```php
<?php // nomeUnico.php

function nomeUnico() {
    echo 'Nome Único!';
}
```

E considere esse outro arquivo, que aciona essa declaração incluindo esse arquivo dentro de si:

```php
<?php // header.php

require(__DIR__ . '/nomeUnico.php');

nomeUnico(); // imprime 'Nome Único!'
```

E então, esse outro arquivo que inclui o `header.php`... Mas acidentalmente incluíram, também, o `nomeUnico.php`:

```php
<?php // index.php

require(__DIR__ . '/header.php');
require(__DIR__ . '/nomeUnico.php'); // Fatal error: Cannot redeclare nomeUnico()
```

Esse erro só aconteceu porque a função em si já havia sido declarada no primeiro `require` executado dentro do arquivo `header.php`. E para solucionar esse problema, tem três jeitos:

### A - `[Best Developer Choice]` Pare de fazer descoberta de funções/classes na mão, use **namespace** com `spl_autoload`!

<center> ![Slap like](https://media.giphy.com/media/10DRaO76k9sgHC/giphy.gif) </center>

Mas tudo bem se não quiser ver isso agora, afinal eu não expliquei nada disso. Porém essa é uma dica de ouro hein? Imagina **só incluir uma função e/ou classe somente quando ainda não foi definida?** Maravilhoso. E ainda garante um padrão **PSR-4** no projeto, se fizer certinho... Ah, maravilha.

### B - Limite a importação da função para uma única vez com `require_once`

Se o arquivo `nomeUnico.php` serve somente para declarar a função, você pode controlar bem o código ao limitar sua inclusão para **somente uma única vez** adicionando a terminologia `_once` no `require`, modificando os arquivos `header.php` e `index.php` para, respectivamente:

```php
<?php // header.php
require_once(__DIR__ . '/nomeUnico.php');

nomeUnico(); // imprime 'Nome Único!'
```

```php
<?php // index.php

require(__DIR__ . '/header.php');
require_once(__DIR__ . '/nomeUnico.php'); // nada acontece feijoada
```

Assim, desde que todo `require` desse arquivo esteja com essa defesa, nada irá declarar a função duas vezes.

### C - `[Best Beginner Choice]` Verifique se a função foi declarada antes de declará-la

Se você sabe que há um risco enorme de outro desenvolvedor desavisado incluir a função sem a terminologia `_once` (e quiser retirar essa responsabilidade de conhecer tudo o que acontece em todo lugar), você pode deixar a declaração segura encapsulando-a com uma verificação simples usando a função `function_exists()`, que retorna `true` quando já existe uma função declarada no nome informado e `false` quando não.

Ou seja, modificando somente o arquivo `nomeUnico.php` para:

```php
<?php // nomeUnico.php
if (!function_exists('nomeUnico')) {
    function nomeUnico() {
        echo 'Nome único!';
    }
}
```

Se você já lidou com **WordPress**, provavelmente já viu um monte desses espalhados por aí... Se encontrar de novo e já estiver manjando de `spl_autoload`, por favor, resolve esse débito técnico, ok?

Eu ouvi um ok??!

<center> ![...](https://media.giphy.com/media/4eGUxJc4lplh6/giphy.gif) </center>

Não tem como eu ter ouvido um ok, mas tudo bem. Vamos para o próximo ponto!

## 2 - As regras de nomenclatura são as mesmas das variáveis

E aqui não tem o que discutir, apenas sentir

```php
<?php

function ehUmNomeValido() {
    return 'oi';
}

function _tambemEhUmNomeValido() {
    return 'vc';
}

function Tambem3h_UmNomeValido() {
    return 'vem';
}

// daqui pra cima é sucesso
// daqui pra baixo é erro

function 1naoEhUmNomeValido() {
    return 'sempre';
}

function $tbmNao() {
    return 'aqui';
}

function mt Menos Assim() {
    return '?';
}
```

## 3 - O uso das funções é **case insensitive**

```php
<?php

function nomeUnico() {
    echo 'Nome único!' . PHP_EOL;
}

// mesmo que você declare assim, com tudo minúsculo e o U maiúsculo
// você pode chamar do jeito que quiser
NOMEUNICO();
nomeunico();
NoMeUnIcO();
NOMEuNICO();

// você só não pode colocar caracteres diferentes da ordem da escrita
N0MEUNICO(); // erro
_nomeUnico(); // erro
```

Da mesma forma, respeitando o primero ponto, você não pode escrever outra função com a mesma nomenclatura mesmo variando as letras maiúsculas e minúsculas.

```php
<?php

function nomeUnico() {
    echo 'Nome único!' . PHP_EOL;
}

// aqui vai dar erro
function nomeunico() {
    echo 'Nome único!' . PHP_EOL;
}
```

## 4 - As funções não são declaradas no momento da **evaluação**

Se você escreve uma função no escopo natural do código, sem nenhuma dependência (como aquele `if` que criei), você poderá escrever sua execução antes mesmo de definí-la sequencialmente. Por exemplo:

```php
<?php

nomeUnico();


function nomeUnico() {
    return 'Funciona!';
}
```

Isso aqui só funciona porque o PHP dá uma compilada no seu código antes de atribuir valores à chamada. Por isso ele consegue saber que a função existe em algum lugar e chamá-la corretamente. Entretanto, se a declaração da sua função depender de uma expressão, aí não funciona, pois a resolução de expressões é feita no momento de **evaluação**, onde há **dependência de um dado**.

```php
<?php

nomeUnico();

if (!function_exists('nomeUnico')) { // expressão dependente
    function nomeUnico() {
        return 'Não funciona =/';
    }
}
```

Mesmo em casos literais isso acontece, pois também são considerados expressões. Experimente trocar o `!function_exists('nomeUnico')` por `true`.

## 5 - Toda função tem contexto GLOBAL

E é fato:

```php
<?php

function declaraNomeUnico() {
    function nomeUnico() {
        echo 'Funciona!';
    }
}

declaraNomeUnico();
nomeUnico(); // mesmo sendo declarada dentro da função, podemos chamá-la do lado de fora
```

----

Enfim, com todos esses exemplos, você deve ter percebido que a escrita segue esse passo-a-passo:

1. começa com `function`;
2. depois colocamos o **nome único da função**;
3. daí abrimos **parênteses** (`(`), onde, nos exemplos acima, ficaram todos vazios;
4. depois fechamos os **parênteses** (`)`);
5. e, em seguida, abrimos o bloco de código a ser executado pela função que estamos definindo, encapsulando com **chaves** (`{}`).

> O que ficaria entre os parênteses, Kiko?

**Os argumentos**, que é o assunto do nosso próximo artigo, pois é bem extenso. Mas são como se fossem *variáveis internas*, onde você pode definir o tipo de dado esperado, um valor padrão, etc. Se você já estiver lidando com PHP 8, tem um recurso bem interessante chamado **Named Arguments** ou **Argumentos Nomeados** que também abordarei no próximo artigo. Por tanto, não esqueça de vir dar uma lida!

E por hoje é só! Curtiu?! Comenta e compartilha! Ainda falta um bocado de coisa para falar sobre funções, mas aqui já deu pra dar um overview básico de como escrevê-las. Nos próximos você só vai aprender como deixá-las mais complexas, hehehehehe. Ah, não esquece de responder minha pergunta subliminar que deixei nos códigos, hein?

**Inté!!**
