PHP do Básico ao Avançado – Aula 7 – Include, Require e Funções de Usuário

Tempo de Leitura: 11 Minutos

Para facilitar nossa vida como desenvolvedor, ao se criar um sistema mais complexo, podemos dividir o problema como diversos blocos, que se interligam e produzem um todo. Agora imagine que esse pedaço pode ser definido como um arquivo, ou como uma função de usuário, e que estas possam ser usadas das mais diversas maneiras. Essa é a idéia por traz dessas 3 definições que estudaremos nessa aula de hoje.

include() e include_once()

A instrução include como o próprio nome diz, inclui um arquivo para ser interpretado pelo PHP, ou seja, acrescenta as instruções contidas nele, naquele ponto. Os arquivos são incluídos baseando-se no caminho do arquivo informado ou, se não informado, o include_path especificado. Se o arquivo não for encontrado no include_path, a declaração include checará no diretório do script que o executa e no diretório de trabalho corrente, antes de falhar. Ele emitirá um aviso (alert) se não localizar o arquivo.

Se um caminho for definido — seja absoluto (iniciando com a letra do drive ou \ no Windows, ou / no Unix/Linux ), ou relativo ao diretório atual (começando com . ou ..) — a definição existente no php.ini  include_path será completamente ignorada, por exemplo, se o nome do arquivo iniciar com ../, o interpretador irá procurar pelo arquivo no diretório pai.

include_path
Especifica uma lista de diretórios onde as funções require, include, fopen(), file(), readfile() e file_get_contents() procuram por arquivos. O formato é como a variável de ambiente PATH uma lista de diretórios separados por dois pontos no Unix ou ponto e vírgula no Windows. O PHP considera cada item no include_path separadamente ao procurar por arquivos para incluir. Ele irá verificar o primeiro caminho, e se não o encontrar, verificar o próximo caminho, até que encontre o arquivo incluído ou retorne com um E_WARNING ou um E_ERROR. Você pode modificar ou configurar o include_path em tempo de execução usando set_include_path().

Quando um arquivo é incluído, o código herda o escopo de variáveis do exato ponto onde ocorreu a inclusão, ou seja, qualquer variável disponível no arquivo que incluiu estará disponível no arquivo incluído, daquela linha em diante. Entretanto, todas as funções e classes definidas no arquivo incluído estarão no escopo global, como se tivessem sido declaradas a partir daquele ponto.

Uma observação, todo o arquivo incluído pelo PHP é aberto como sendo um arquivo do tipo definido como padrão no php.ini na diretiva default_mimetype=”text/html”, que por padrão é um html, para que o PHP possa interpretar o seu conteúdo, este deve estar entre as tags de abertura e fechamento (<?php e ?>). Um outro ponto a ser observado, é que se o pnp.ini tiver as diretivas allow_url_include e allow_url_fopen habilitadas, é possivel incluir um arquivo existente em outro host, mais la na frente, vamos abordar diretamente esses procedimentos quando estiver-mos falando de segurança, pois estes arquivos podem ter conteúdos além do controle do nosso script e portanto, devem ser usados com muita cautela.

A instrução include retorna FALSE ao falhar ou não localizar o arquivo, e emite um aviso. Já inclusões bem sucedidas, ao menos que sejam sobrescritas pelo arquivo incluído, retornam o valor 1 (true). É possível utilizar a declaração return dentro do arquivo incluído para finalizar o processamento e retornar para o arquivo que o incluiu. Além disso, é possível retornar valor a partir do arquivo incluído. Pode-se usar o valor do arquivo incluído como em uma função normal. Isso não é, entretanto, possível quando incluímos arquivos remotos a menos que a saída do arquivo remoto tenha tags válidas de início e fim do PHP (como em um arquivo local). Pode-se declarar as variáveis necessárias dentro dessas tags e estarão disponíveis em qualquer ponto do arquivo que o incluiu.

include_once()

Funciona exatamente igual ao include(), porém, caso o diretório/arquivo já tenha sido incluído anteriormente, ele não será novamente incluído. Isso garante, que se determinados arquivos por exemplo contendo funções declaradas, não gere um erro de redeclaração. Uma observação importante, é que mesmo que ele já tenha sido previamente incluído o retorno da chamada ao construtor include_once() vai retornar como 1 (true).

Vamos ver alguns exemplos de inclusão de arquivos:

file1.php
<?php 
$a=10;
?>

index.php
<?php 
$a=1;
echo $a; //imprime o valor 1
include('file1.php');
echo $a; //imprime o valor 10
$a=2;
echo $a; //imprime o valor 2
include_once('file1.php');
echo $a; //imprime o valor 2, pois o include_once considera que o arquivo já foi incluido anteriormente e não o faz novamente
?>

require() e require_once()

As instruções require e require once são análogas as instruções include e include_once respectivamente, a diferença se dá, que usando o construtor require, caso o arquivo não seja localizado, a execução do script para, com um erro (E_COMPILE_ERROR), ou seja, usando o require, caso o arquivo não exista o script é interrompido naquele ponto.

Como include e require são utilizados?

Basicamente os arquivos incluídos por estas instruções são partes de código que podem ser reutilizados em diversos pontos diferentes e em situações diferentes, imagine, por exemplo a conexão ao banco de dados, essa informação deve ser utilizada por todos os scripts que precisam acessar ou manipular algum dado no banco de dados, poderíamos simplesmente em cada arquivo do nosso script, colocar uma chamada para a função:

$pdo = new PDO("mysql:host=servidor.com;dbname=banco_de_dados", 'usuario_master', 'senha_1234');

Agora, imagine que tenhamos 100 arquivos diferentes que fazem acesso aos dados, teríamos essa mesma instrução repetida nos 100 lugares e nosso sistema precisa trocar de servidor para um diferente, por exemplo para um servidor no brasil, você vai ter que acessar esses 100 arquivos e mudar a instrução para:
$pdo = new PDO("mysql:host=servidor.com.br;dbname=banco_de_dados", 'usuario_master', 'senha_1234');

Veja, é uma alteração simples, você pode esquecer de mudar em 1 arquivo, afinal, nós somos passiveis de erro, além da carga de trabalho, e do tempo que levaria. Se essa chamada estivesse em um arquivo separado, bastaria acessar esse arquivo e alterar. E esse é um arquivo requerido, ou seja, se ele estiver indisponível nosso sistema tem que parar a execução, pois significa que não conseguiríamos nos conectar ao servidor de dados.

Ah, e quando usamos um include? Bem, agora imagine uma situação um pouco diferente, um sistema de um colégio, onde quando o aluno faz o login no seu ambiente, colocamos alguns destaques de artigos ou notícias que estão no site do colégio, que é um sistema que fica hospedado em outro ambiente que pode não estar disponível a todo o tempo, se o arquivo não tá acessível, simplesmente continuamos e deixamos a informação que não é crucial de fora.

Então, podemos ter um único arquivo com todo o conteúdo? NÃO, o PHP é uma linguagem interpretada, ou seja, todo o conteúdo é previamente analisado e processado para que a saída da execução seja feita, ter tudo em um só bloco vai gerar uma enorme carga desnecessária par nosso servidor, e consumir recursos, seria como usar uma moto serra no lugar de um fatiador de frios, é possível, mais o efeito colateral não seria justificável imagina só a sujeira.

Então, pensemos como se esses arquivos contenham códigos específicos para realizarem um procedimento, imagine uma situação, onde temos um objetivo total, por exemplo ir ao mercado e fazer as compras do mês. Para isso precisamos basicamente de algumas coisas, fazer a lista do que precisamos, nos deslocar até o supermercado escolhido, pegar os produtos  e colocar no carrinho, passar no caixa, pagar, voltar para casa e guardar tudo. Esses dados são parecidos com por exemplo ir a feira, então, cada um desses grupos de ações ou funções pode ser definido em um arquivo separado, diferente de uma função (que veremos mais a frente) esses arquivos podem conter declarações de funções, ou simplesmente ter um pedaço de código HTML como um menu, ou uma opção diferente de temas de cores em um CSS enfim, vamos ver mais lá na frente como eles são amplamente utilizados.

Funções do usuário

O PHP nos permite, como praticamente qualquer linguagem atual, criar funções, que são blocos de código que como seu próprio nome diz, tem como objetivo realizar uma tarefa específica, uma das boas práticas de desenvolvimento é usar funções sem sobrecarrega-las, ou seja, torna-las o mais simples possível, para realizar apenas o que ela é proposta a fazer.

Uma função, bem definida deve receber uma entrada, realizar um processamento e retornar uma saída. Qualquer código PHP válido pode aparecer dentro de uma função, mesmo outras funções e definições de classes, porém, essas duas ultimas informações devem ser evitadas, por questões de legibilidade fazendo parte das boas práticas de programação. Um outro uso que devemos evitar sempre que possível e a saída de texto (echo e print) diretamente por uma função, para esse tipo de processamento é que existem as outras construções como o include ou o require ou mesmo a definição de classes e outras estruturas. Se necessário uma saída textual da função é uma boa prática retorna-la com um return como em:

<?php
function ola_mundo(){
   return 'Olá Mundo';
}

echo ola_mundo();
?>

Nomes de funções seguem as mesmas regras que outros rótulo no PHP. Um nome de função válido começa com uma letra ou um sublinhado, seguido, seguido por qualquer número de letras, números ou sublinhado. As funções não precisam ser criadas antes de serem referenciadas, exceto quando uma função é condicionalmente definida, o que também não é uma boa prática. Todas as funções e classes no PHP tem escopo global – elas podem ser chamadas fora de uma função mesmo que tenham sido definidas dentro e vice-versa.

Note que podemos passar argumentos para as nossas funções, como por exemplo:

<?php
function soma(...$ns) {
    $resultado = 0;
    foreach ($ns as $n) {
        $resultado += $n;
    }
    return $resultado;
}

echo soma(1, 2, 3, 4);
echo "<br>";
echo soma(1,2,3,4,5);
echo "<br>";
echo soma(2,4);
echo "<br>";
echo soma(5);
?>

Ou usar um valor padrão, como em:

<?php 
function quadrado ($num = 2) {
    return $num * $num;
}
echo quadrado(4); // imprime '16'
echo quadrado(); //imprime 4, pois por padrão identifica que 2 é o numero passado.
?>

Você também pode forçar a conversão de tipos, como em:

<?php
function quadrado(int $num = 2) {
  return $num * $num;
}
echo quadrado(4); // imprime '16'
echo quadrado(2.2); //imprime 4, pois por padrão identifica que 2.2 era um float e o converte para o inteiro
?>

Por padrão, e se possível, o PHP irá converter o tipo incorreto no tipo escalar esperado. Por exemplo, uma função que passa um parâmetro integer onde se espera uma string receberá o valor com o tipo string. Ou se é uma string com um valor numeral, este também será convertido. É possível habilitar o modo estrito arquivo a arquivo. No modo estrito somente uma variável do exato tipo especificado na declaração será aceito, ou uma exceção TypeError será lançada. A única exceção é o tipo integer que poderá ser entregue a uma função esperando um float.

Retornando valores

Valores podem ser retornados utilizando a instrução return. Qualquer tipo pode ser retornado, incluindo arrays e objetos. Isto faz com que a função termine sua execução imediatamente e passa o controle de volta para a linha de onde ela foi chamada (stack).

Note, que é perfeitamente possível utilizar instruções echo, print, print_r, sprint entre outras que produzam algum tipo de saída, ou mesmo escapar HTML dentro de uma função, porém não é um comportamento desejável, para se seguir as melhores convenções para codificação, se dentro de sua função houver alguma saída de texto ou conteúdo, não será possível o envio posterior de headers ou cookies, por este motivo, você pode utilizar a saída retornada por um return, e atribuir esse valor a uma variável.

O PHP 7 acrescenta suporte a declaração de tipo de retorno. Os mesmos tipos que estão disponíveis para declaração de argumentos estão disponíveis para tipagem de retornos. No modo padrão (tripagem fraca) o valores retornados serão convertidos para o tipo correto caso não enquadrem no tipo informado. No modo de tipagem forte os valores retornados precisam ser o tipo correto ou uma exceção TypeError será lançada. Veja um exemplo:

<?php
function sum($a, $b): float {
    return $a + $b;
}

// Note que um float será retornado.
var_dump(sum(1, 2));
?>

Note que sempre o retorno será do tipo float, indiferente dos argumentos terem sido inteiros ou float.

Funções Internas

O PHP possui uma série de funções, que o acompanham por padrão, e uma outra série de funções que podem ser adicionadas através de extensões que podem ser carregadas ou compiladas em conjunto, por exemplo a função mysqli_connect() só está disponível se a extensão mysqli estiver carregada.

Nota Técnica: Se os parâmetros dados a uma função não forem o que ela espera, como passar um array aonde uma string é esperada, o valor de retorno da função é indefinido, para a maioria, irá retornar NULL mas isto é apenas uma convenção, e você não pode depender disso.

O PHP possui uma função interna chamada function_exists() onde é passado o nome da função e ela retorna se a função está ou não definida, podendo ser uma função interna, uma função de uma biblioteca ou uma função definida pelo usuário, por exemplo:

<?php
if (function_exists('imap_open')) {
    // se as funções IMAP estão disponíveis, utilize-as no seu programa
    echo "Implementação IMAP está disponível para uso";
} else {
    echo "IMAP não disponível, informe o erro, ou use POP3 por exemplo";
}
?>

Você pode utilizar este construtor para criar plugins para seus softwares, ou para usar alternativas caso uma extensão não esteja ativa, ou mesmo para prevenir erros em geral.

Conclusão

Neste ponto do curso, aprendemos a dividir um todo em partes, e a utilizar essas partes com os arquivos de inclusão, funções e o básico sobre as ferramentas de reutilização de código. Na próxima aula, vamos falar sobre os erros que podem ocorrer, e como vamos tratar esses erros e outras exceções que podem ocorrer durante a execução.