Aproveite o mês das
carreiras na Alura

Até 44% OFF

Falta pouco!

00

DIAS

00

HORAS

00

MIN

00

SEG

Alura > Cursos de Programação > Cursos de PHP > Conteúdos de PHP > Primeiras aulas do curso PHP: avançando em tipagem, performance e estruturas de controle

PHP: avançando em tipagem, performance e estruturas de controle

Tipagem e Funcionamento Interno do PHP - Apresentação

Apresentando o curso e o instrutor

Olá! Sejam muito bem-vindos à Alura. Meu nome é Vinícius Dias e serei o guia neste curso, no qual nos aprofundaremos na linguagem PHP.

Audiodescrição: Vinícius é um homem branco, de cabelo curto e escuro, com bigode e cavanhaque. Ele veste uma camisa azul escura do PHP Manaus.

Explicando o foco do curso

Se já conhecemos o básico da sintaxe do PHP e conseguimos escrever alguns programas, este curso é ideal para nós, pois entenderemos melhor a linguagem em si. Não estudaremos muita sintaxe nova ou novas funcionalidades; o foco será compreender como o básico funciona.

Abordaremos os tipos no PHP, quais são esses tipos e como podemos utilizá-los. Além disso, exploraremos como a linguagem é efetivamente executada nos bastidores, com detalhes.

Explorando estruturas de controle e operadores

Vamos discutir mais sobre estruturas de controle, um tópico que abordamos rapidamente em cursos anteriores e que merece mais atenção. Além disso, vamos explorar detalhadamente os operadores da linguagem, analisando como podemos operar sobre valores e expressões. Nosso objetivo é nos aprofundar na manipulação de valores com PHP.

Incentivando a participação e interação

Caso surjam dúvidas durante o curso ou algo não fique claro, temos um fórum na Alura onde sugerimos que você abra um tópico. Também disponibilizamos um servidor no Discord para uma interação mais dinâmica, troca de ideias e discussões. Recomendamos que você participe de ambos, inclusive para ajudar outras pessoas e responder perguntas.

Concluindo a introdução do curso

Esperamos que você aproveite bastante o curso, aprenda muito, e nos vemos no próximo vídeo, onde começaremos a falar sobre tipos no PHP.

Tipagem e Funcionamento Interno do PHP - Tipos no PHP

Introduzindo tipos no PHP

Nesta aula, vamos discutir sobre tipos no PHP. Primeiramente, vamos analisar o código que temos do ScreenMatch. Temos um arquivo de funções separado do nosso arquivo principal, o index. Nesse arquivo, chamamos algumas funções, como incluidoNoPlano e exibeMensagemNoLancamento. Essas funções possuem definições de tipos nos parâmetros e no retorno. Já falamos sobre o void, que representa a ausência de tipos. Portanto, já trabalhamos com tipos no PHP, mas não abordamos tanto a teoria. Vamos entender melhor e detalhar essa parte de tipos no PHP. Não abordaremos tudo, pois há muitos detalhes, mas a documentação está sempre disponível para esclarecer dúvidas. Vamos falar sobre diversos aspectos.

Vamos abrir um arquivo vazio para fazer anotações e mostrar exemplos, se necessário. Primeiramente, já conhecemos alguns tipos, os principais tipos escalares do PHP. Por exemplo, temos string, que é um tipo textual. Vamos ver como isso é representado no código:

$string = 'Valores textuais';

Explorando tipos escalares e compostos

Em seguida, temos o tipo int, que possui valores numéricos inteiros:

$int = 27;

O float, que em alguns momentos pode ser chamado de double no PHP, possui valores decimais:

$float = 15.5;

Temos também o bool, que representa valores booleanos, verdadeiro ou falso. Veja como podemos definir isso:

$bool = true;
$bool = false;

Esses são os valores escalares, simples, que contêm um único valor. Em algumas linguagens, string não é considerado um valor escalar, pois é um conjunto de caracteres. No PHP, string é um valor escalar.

Além disso, temos tipos complexos ou compostos, como o array. Um array pode conter vários valores, como um array de notas utilizado no ScreenMatch. Vamos criar um array vazio e depois adicionar alguns valores:

$array = [];
$array = [134, 348417, 945718];

Compreendendo arrays e conversões de tipos

Um array, ou vetor, é um conjunto de valores organizados sequencialmente. No PHP, a implementação não é necessariamente um vetor na memória RAM, mas para nós, que utilizamos, ele está organizado sequencialmente, permitindo acesso aos índices de forma sequencial. Podemos acessar os valores do array assim:

echo $array[0];
echo $array[1];
echo $array[2];

No PHP, um array pode conter qualquer tipo de dados, inclusive todos os tipos mencionados anteriormente. Por exemplo, um array pode conter uma string, um int, um float e um bool sem problemas:

$array = [$string, $int, $float, $bool];

Portanto, temos tipos escalares e compostos. Existem outros tipos compostos no PHP, mas focaremos no array por enquanto, para não adicionar complexidade desnecessária.

Um ponto importante é a conversão entre tipos, como o type cast, que é uma conversão explícita de um tipo. Por exemplo, podemos ter uma string com valor numérico e convertê-la para int. O PHP faz essa conversão para nós, transformando uma string numérica em um int. Vamos ver como isso é feito:

$valorNumerico = '27';
$valorInteiro = (int) $valorNumerico;

Realizando type casting e type juggling

Se a string contiver apenas números, o PHP consegue convertê-la para int. Se houver um valor decimal, como 27,5, ao converter para int, o PHP remove a parte decimal, resultando em 27:

$valorDecimal = 27.5;
$valorInteiro = (int) $valorDecimal;
var_dump($valorInteiro);

Podemos realizar type casting em tipos escalares no PHP. Por exemplo, podemos converter uma string para bool. Uma string não vazia é interpretada como verdadeira, enquanto uma string vazia é falsa:

var_dump((bool) $string);
var_dump((bool) '');

O PHP realiza type juggling, ou malabarismo de tipos, tentando ajudar nas conversões, mesmo que não façam sentido. Por exemplo, uma string não numérica convertida para int será 0. Uma string que começa com números, seguida de caracteres, será convertida até a parte numérica:

var_dump('Valor numérico' == 0);
var_dump('27' == 27);
var_dump('27' === 27);

Analisando comparações e coerção de tipos

Ao converter para float, uma string numérica será convertida corretamente. Se a string contiver um número seguido de caracteres, o PHP converterá até a parte numérica:

var_dump((float) '27 maçãs');
var_dump((float) '27.5');
var_dump((float) '27.5maçãs');
var_dump((float) '27.5e');
var_dump((float) '27 .5');

Precisamos ter cuidado com conversões de tipos e type juggling no PHP. Agora, vamos falar sobre comparações. Quando fazemos uma comparação em um if, o PHP converte a string para bool e compara com verdadeiro. Uma string não vazia é verdadeira, enquanto uma string vazia é falsa. Isso pode ser verificado com um vardump, que exibe o valor e o tipo de uma variável. Ao executar o código, podemos ver que uma string não vazia resulta em verdadeiro, enquanto uma string vazia resulta em falso:

if ($string) {
    echo 'Verdadeiro' . "\n";
}

if ('') {
    echo 'Verdadeiro' . "\n";
} else {
    echo 'Falso' . "\n";
}

Executando operações booleanas e comparações

Quando executamos uma operação booleana ou de comparação no PHP, o comportamento segue as regras de conversão explícita. Sempre que utilizamos um valor como booleano em uma expressão, como em um if ou while, o PHP realiza essa conversão. Por exemplo, um inteiro diferente de zero é considerado verdadeiro, enquanto zero é falso. O mesmo se aplica a floats: zero é falso e qualquer outro valor é verdadeiro, independentemente de ser positivo ou negativo:

if (1) {
    echo 'Verdadeiro' . "\n";
}

if (0) {
    echo 'Falso' . "\n";
}

if (0.0) {
    echo 'Falso' . "\n";
}

if (0.1) {
    echo 'Verdadeiro' . "\n";
}

if (-0.1) {
    echo 'Verdadeiro' . "\n";
}

Ao realizar comparações, o PHP pode fazer conversões. Se fizermos um vardump de uma string numérica igual a zero, a conversão de string para inteiro resultará em verdadeiro. No entanto, ao executar, o resultado é falso. Em versões anteriores do PHP, isso retornaria verdadeiro, mas atualmente, o PHP realiza o type juggling (malabarismo de tipos). Quando comparamos uma string com outro tipo, o PHP converte o outro tipo para string e compara ambos como strings:

var_dump('Valor numérico' == 0);
var_dump('27' == 27);

Comparando strings e inteiros

Até a versão 8.1 ou 8.2, ao comparar uma string com um inteiro, a string era convertida para um valor inteiro. Se a string não fosse numérica, seria convertida para zero, resultando em verdadeiro. Nas versões recentes, isso retorna falso. Se compararmos uma string numérica com um valor numérico, o resultado será verdadeiro, pois ocorre a conversão de strings numéricas:

var_dump('27' == 27);
var_dump('27' === 27);

Em comparações de maior ou menor, como 27 > 26, o PHP exibe verdadeiro, enquanto 27 > 28 resulta em falso. Para strings não numéricas, como "test" > 28, o PHP compara o código ASCII, onde letras vêm depois de números. Assim, "test" é considerado maior que 28:

var_dump('27' > 28);
var_dump('teste' > 28);

Lidando com funções e strict types

Ao chamar uma função que espera um inteiro, podemos passar uma string ou um float. Isso gera um aviso de conversão implícita, mas a execução continua. Se passarmos uma string como "2025", não haverá aviso. Podemos desativar esse tipo de conversão usando strict_types=1, que interrompe conversões de tipos. Nesse caso, a IDE avisa sobre o erro de tipo, e a execução resulta em erro, pois a string não é convertida para inteiro. Para resolver, podemos fazer um casting ou usar a função intval:

declare(strict_types=1);
exibeMensagemLancamento('2025');
exibeMensagemLancamento((int) '2025');
exibeMensagemLancamento(intval('2025'));

Concluindo sobre conversões e comparações

Falamos sobre conversão de tipos, onde o type casting é explícito e o type coercion (coerção de tipos) é implícito. Na documentação do PHP, há uma seção sobre type juggling em diferentes contextos, como numérico, string e lógico. Existe uma tabela de comparação que mostra, por exemplo, que verdadeiro comparado com zero retorna falso, mas com um retorna verdadeiro, usando comparação mais permissiva.

Por fim, há uma diferença entre o operador ==, que realiza type juggling, e o operador ===, que faz uma comparação estrita. O operador === verifica primeiro o tipo; se forem diferentes, retorna falso. Se os tipos forem iguais, verifica a igualdade dos valores. O operador == tenta converter os valores para comparar. Ao executar, obtemos true e false, pois o operador === verifica se os valores são idênticos em tipo e valor, enquanto == verifica a igualdade com possíveis conversões de tipo:

var_dump('27' == 27);
var_dump('27' === 27);

Deixaremos alguns links para consulta, incluindo a tabela de comparação com diferentes tipos de comparação. Exploramos bastante sobre tipos e como a linguagem funciona. No próximo vídeo, entenderemos melhor o que acontece quando executamos um comando PHP na linha de comando.

Tipagem e Funcionamento Interno do PHP - Como a linguagem funciona

Discutindo a tipagem dinâmica do PHP

No vídeo anterior, discutimos que o PHP é uma linguagem de tipagem dinâmica. Isso significa que os tipos são verificados em tempo de execução. Podemos ter uma variável com um valor do tipo string e, posteriormente, alterar essa mesma variável para um valor numérico. Isso é permitido no PHP devido à sua tipagem dinâmica. Os tipos são verificados em tempo de execução, ou seja, no momento de compilação do PHP, os tipos das variáveis e os valores que podemos ter não são verificados.

Para ilustrar isso, podemos começar com uma variável que inicialmente armazena uma string:

$variavel = 'string';

E, em seguida, podemos alterar essa mesma variável para armazenar um valor numérico:

$variavel = 127;

Explicando a execução e compilação no PHP

O ponto que queremos destacar é a diferença entre tempo de execução e tempo de compilação. O PHP é conhecido como uma linguagem interpretada, o que é verdade, mas também possui um processo de compilação. Se conhecemos outras linguagens, como C# ou Java, o PHP funciona de maneira semelhante, onde o código é transformado em algo intermediário e o interpretador executa esse intermediário.

Para entender como o PHP executa um código, abrimos o terminal e digitamos php seguido de algum arquivo. O PHP sempre inicia a execução por um arquivo. Quando acessamos um endereço na web, como site.com/home, por exemplo, por trás das configurações, sempre há um arquivo principal sendo executado. Portanto, ao lidarmos com PHP, existe um arquivo que é nosso ponto de entrada. Em outras linguagens, há uma função main, mas no PHP, o início do código é sempre um arquivo que inclui outros por meio de require. A partir desse require, o código é adicionado ao conjunto de códigos e executado.

Descrevendo o processo de tokenização e parsing

Compreendido esse ponto inicial sobre a execução do PHP, ao informar qual arquivo queremos que seja interpretado, vários processos são executados. Para explicar melhor esses processos, utilizamos uma imagem do site thephp.website, um site bastante conhecido. O interpretador inicia a execução verificando se essa execução já foi feita antes. Se o arquivo já foi executado anteriormente no servidor, ele verifica. Caso seja a primeira execução, ele realiza um processo chamado tokenizing, transformando o código em tokens, como tokens de identificação de variável, atribuição, valor, finalização de expressão, entre outros.

Com a tokenização, o código é separado em tokens e o PHP tenta realizar o parse, verificando a sintaxe do código. Se houver um erro, como a falta de um ponto e vírgula, o PHP interrompe a execução, não executando nenhuma linha do código. Mesmo que haja um var_dump antes do erro de sintaxe, ele não será executado. O PHP não lê linha a linha para depois encontrar um erro.

Gerando a árvore de sintaxe abstrata e compilando o código

Por exemplo, se tivermos o seguinte código:

var_dump(1);
$string = 'Valores textuais';

E esquecermos o ponto e vírgula no final da linha, o PHP não executará nenhuma parte do código.

Após corrigir os erros de sintaxe, o PHP gera uma árvore de sintaxe abstrata (Abstract Syntax Tree), que é uma representação dos tokens e, por sua vez, do código. Isso permite a compilação, transformando o código em binário, que a máquina entende. O resultado da compilação é uma representação intermediária, ou OPCodes (códigos de operação), armazenada em uma extensão chamada OPCache. O OPCache armazena o código pré-compilado, quase em código de máquina.

Executando o código com Zend Engine e OPCache

Após todo esse processo de compilação, o código é executado pelo interpretador do PHP, chamado Zend Engine. Ao executar php -v no terminal, podemos ver a versão do Zend Engine, que é o motor de interpretação. Criado pela Zend, uma empresa de tecnologia, hoje é mantido pela equipe do PHP. Assim, temos a versão do PHP, a versão da linguagem e a versão do interpretador após o processo de compilação.

Portanto, ao acessar um site como alura.com.br/cursos, o código PHP é executado pela primeira vez, passando por todo esse processo.

Explicando o conceito de just-in-time compiler

Ele realizou a tokenização, transformou em tokens, fez o parse, verificou que a sintaxe estava correta, compilou para essa representação intermediária e salvou no cache. Quando acessamos novamente esse arquivo, cada um dos arquivos dessa execução, ele verifica: isso já está disponível no cache? Se estiver, ele não repete todo o processo. Ele não recompila o código, pois já está compilado. Assim, ele parte para a execução do código. Com isso, obtemos ganho de performance, ao não precisar interpretar o arquivo toda vez que o executamos. Se alterarmos o arquivo, podemos fazer com que ele seja recompilado de forma automática ou manual. Isso já entra na parte de web. Vamos deixar um material para saber mais sobre o PHP na web, mas isso já entraria mais na parte de web. No nosso caso, como estamos executando pela linha de comando, não temos esse cenário do opcache ativo. Essa memória compartilhada entre os processos do servidor web não está ativa. Portanto, sempre que alteramos o arquivo, não precisamos nos preocupar com configurações para saber se ele será atualizado ou se será executada a versão mais nova.

Entendemos como tudo isso é executado até este ponto. No entanto, há outro detalhe que ainda não mencionamos: o might compile opcodes. O que isso significa? O código gerado e armazenado é chamado de opcode, um código de operação que é quase um código de máquina, quase executado diretamente na CPU. Quem executa esse opcode é a Zend Engine. A Zend Engine é um código compilado que é executado na CPU, e ela executa nosso opcode. Algumas partes do código, se passíveis de otimização, utilizam um conceito chamado just-in-time (JIT), ou compilador em tempo real. O que é isso? É um compilador que atua no momento da execução. Enquanto o código está sendo executado, uma rotina pode ser compilada para a linguagem de máquina, e isso é armazenado. As instruções de CPU são executadas diretamente na CPU. O PHP possui esse conceito de just-in-time compiler.

Comparando compiladores AOT e JIT

Existem dois tipos de compiladores: AOT (ahead of time) e JIT. Por exemplo, quem conhece C e utiliza o GCC para compilar o código em C, gerando um arquivo executável, está utilizando um compilador ahead of time, que executa a compilação antes da execução. O Java C é um compilador ahead of time, que executa a compilação antes de executar e gera os bytecodes. No caso do PHP, temos um just-in-time compiler. Conforme o código é executado, ele pode ser compilado para a linguagem de máquina e interpretado diretamente pela CPU, sem passar pela Zend Engine. Esse tipo de compilador pode ser habilitado através das configurações do PHP, sendo muito interessante em casos de computação intensa. Por exemplo, ao realizar atividades de inteligência artificial ou executar um modelo pré-treinado de inteligência artificial com PHP, o just-in-time compiler habilitado torna o processo mais rápido. Ao processar muitas imagens, isso é feito de forma mais rápida com o just-in-time. Quando temos processos que utilizam muita CPU, o just-in-time compiler é bastante útil. Em um cenário de aplicação simples, que apenas acessa o banco de dados ou faz chamadas para outros microserviços, uma aplicação web mais tradicional, o just-in-time compiler pode ajudar, mas não tanto. Novamente, o just-in-time compiler é muito útil em cenários de computação intensiva, com muito código no processador, cálculos matemáticos, processamento de valores numéricos, etc.

Explorando materiais complementares e execução na web

Vamos deixar mais um material para saber mais, abordando como o PHP funciona por trás dos panos, com mais detalhes sobre o que já discutimos, incluindo o Opcache e o just-in-time compiler. Esses materiais complementares adicionam ao que já falamos, com mais detalhes. Assim, entendemos como o PHP funciona por trás dos panos. Na web, temos algumas formas de executar o PHP. Vimos no final do curso anterior a execução do PHP-S e o endereço onde escutamos, por exemplo, o localhost e uma porta, iniciando um servidor web no PHP. Quando iniciamos esse servidor web, o processo que fica rodando possui essa memória compartilhada com o Opcache. Assim, conseguimos utilizar o Opcache e configurar para que ele não revalide o arquivo, não sendo recompilado se modificado. Mesmo que modifiquemos e atualizemos no navegador, veremos o mesmo arquivo, o mesmo resultado antes da alteração. Nesse formato de execução, o Opcache atua.

Iniciando um servidor web localmente

Para iniciar um servidor web localmente, podemos usar o seguinte comando:

php -S localhost:7824

Existem outras formas de execução, como o PHP-FPM, um servidor de aplicações do PHP. Existem cursos mais avançados que abordam o PHP-FPM, e conforme avançamos, entramos mais nesse cenário de configuração de um servidor de produção web. Discutimos o PHP-FPM e cenários onde utilizamos a linha de comando para iniciar uma aplicação e deixá-la rodando continuamente. Nesse cenário, não precisamos do Opcache, pois todo o código já está em memória e sendo executado o tempo todo. O código não deixa de existir e depois é carregado novamente.

Concluindo a discussão sobre PHP

Já discutimos bastante, e nem tudo precisa ficar 100% claro agora, no início da carreira com PHP. Por isso, mencionamos no início que este é um curso para nos aprofundarmos na linguagem. Algumas coisas farão mais sentido conforme estudamos outros assuntos, mas aqui entendemos, pelo menos superficialmente, como a linguagem funciona. Na próxima aula, vamos falar sobre alguns operadores e estruturas de decisão que abordamos nos cursos anteriores, mas não em detalhes. Na próxima aula, vamos nos aprofundar em outras partes da linguagem.

Sobre o curso PHP: avançando em tipagem, performance e estruturas de controle

O curso PHP: avançando em tipagem, performance e estruturas de controle possui 107 minutos de vídeos, em um total de 30 atividades. Gostou? Conheça nossos outros cursos de PHP em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Escolha a duração do seu plano e aproveite até 44% OFF

Conheça os Planos para Empresas