PHP Como Funciona
Quando você digita o endereço de um site e aperta Enter, muita coisa acontece em menos de um segundo. Nesta aula você vai seguir esse caminho de perto: o navegador faz um pedido, o servidor chama o PHP, o PHP roda o seu código e devolve HTML, e o navegador desenha a página. Entender esse caminho evita metade das confusões de quem começa.
- Quem são os personagens: navegador, servidor web e PHP.
- O caminho de um pedido (requisição) e da resposta, passo a passo.
- O que o navegador realmente recebe, conferido com o
curl. - A diferença entre o PHP (no servidor) e o JavaScript (no navegador).
- Os dois jeitos de rodar o PHP: no terminal (CLI) e na web.
A ideia: um restaurante
Pense num restaurante. Você (o cliente) não entra na cozinha: faz o pedido ao garçom. O garçom leva o pedido à cozinha, o cozinheiro segue a receita e monta o prato, e o garçom traz o prato pronto até a mesa. Você come o prato; a receita fica na cozinha.
| No restaurante | Na web | O que faz |
|---|---|---|
| Cliente | Navegador (Chrome, Firefox, Safari…) | Pede uma página e mostra o resultado na tela. |
| Garçom | Servidor web (Apache, nginx ou o php -S) | Recebe os pedidos, decide quem cuida de cada um e devolve as respostas. |
| Cozinheiro | PHP | Executa o código do arquivo .php e produz o HTML. |
| Receita | O arquivo .php | As instruções. Ficam no servidor. |
| Prato pronto | O HTML gerado | É o que vai para o navegador. |
| Despensa | Banco de dados, arquivos | De onde o PHP tira os "ingredientes" (produtos, usuários, notas). |
Duas palavras vão aparecer o tempo todo no guia: o pedido do navegador se chama requisição (em inglês, request) e o que volta se chama resposta (response). A "língua" que os dois usam para conversar é o HTTP (é por isso que os endereços começam com http:// ou https://; o s quer dizer que a conversa é criptografada).
O caminho, passo a passo
A Ana tem na pasta site este arquivo, a página inicial da lojinha dela:
<?php // Este comentário fica no servidor. $senhaDoBanco = "segredo123"; $produtos = 3 + 4; ?> <h1>Lojinha da Ana</h1> <p>Temos <?= $produtos ?> produtos.</p>
O arquivo tem duas partes. Em cima, entre <?php e ?>, código PHP: um comentário (uma anotação para humanos, que o PHP ignora), uma variável com uma senha e uma conta. Embaixo, HTML comum, com um <?= $produtos ?> no meio, que quer dizer "escreva aqui o valor de $produtos". Agora siga o que acontece quando alguém visita http://localhost:8000/loja.php:
- O navegador faz a requisição. Ele se conecta ao servidor
localhost(o próprio computador) na porta8000e manda uma mensagem de texto:GET /loja.php HTTP/1.1, ou seja, "me dê o arquivo/loja.php". - O servidor web recebe e decide. O arquivo termina em
.php, então o servidor não o entrega como está: passa para o PHP. - O PHP executa o arquivo de cima para baixo. Ignora o comentário, guarda a senha na variável, calcula
3 + 4e guarda7. O HTML de fora das marcas vai sendo copiado para a resposta; no lugar do<?= $produtos ?>, ele escreve7. - O PHP termina e entrega o resultado ao servidor. As variáveis são jogadas fora. A cada nova visita, tudo começa do zero.
- O servidor manda a resposta ao navegador: um "cabeçalho" com informações (deu certo? que tipo de conteúdo é?) e, depois, o HTML.
- O navegador desenha a página. Ele recebeu só HTML, e é isso que ele sabe mostrar.
Em forma de desenho:
NAVEGADOR SERVIDOR WEB PHP
│ │ │
│ GET /loja.php ───────▶ │ │
│ │ "é .php: sua vez" ───▶ │ roda loja.php
│ │ │ 3 + 4 = 7
│ │ ◀───── HTML pronto │
│ ◀──── 200 OK + HTML │ │
│ │ │
desenha a página
Na internet, o servidor é um computador num centro de dados. Mas, enquanto você estuda, o servidor é o seu próprio computador: o endereço localhost quer dizer "esta máquina aqui". O navegador e o servidor rodam lado a lado, e o caminho é o mesmo. A aula O Servidor Embutido ensina a ligar esse servidor de testes.
O que o navegador realmente recebe
Dá para "ser o navegador" no terminal com o curl, um programa que faz requisições HTTP e mostra a resposta crua, sem desenhar nada. A Ana ligou o servidor de testes na pasta site (com php -S localhost:8000, em outro terminal) e pediu a página:
$ curl localhost:8000/loja.php <h1>Lojinha da Ana</h1> <p>Temos 7 produtos.</p> « o 7 já veio calculado
Compare com o arquivo loja.php. Sumiram:
- o
<?phpe o?>; - o comentário
// Este comentário fica no servidor.; - a variável
$senhaDoBancoe o valor dela; - a conta
3 + 4(só o resultado,7, chegou).
É exatamente isso que o navegador recebe, e é isso que aparece quando você usa "Exibir código-fonte da página". O código PHP nunca sai do servidor. É por isso que sites guardam a senha do banco de dados em arquivos PHP sem medo: quem visita não tem como lê-la.
Vendo a conversa inteira
Com a opção -i (de include, "incluir"), o curl mostra também o cabeçalho da resposta, a parte que o navegador lê mas não mostra:
$ curl -i localhost:8000/loja.php HTTP/1.1 200 OK « 200 = deu certo Host: localhost:8000 Date: Fri, 16 Oct 2026 23:49:17 GMT « data e hora da resposta (no fuso de Greenwich) Connection: close X-Powered-By: PHP/8.5.8 « "feito com PHP 8.5.8" Content-type: text/html; charset=UTF-8 « o conteúdo é HTML, com acentos em UTF-8 <h1>Lojinha da Ana</h1> « depois da linha em branco, o HTML <p>Temos 7 produtos.</p>
- HTTP/1.1 200 OK
- A linha de status: a versão do HTTP e o código do resultado.
200é sucesso;404é "não encontrado";500é "erro no servidor". - X-Powered-By
- Um aviso que o PHP acrescenta dizendo a versão. Em sites de verdade, costuma ser desligado (quanto menos um invasor souber, melhor).
- Content-type
- O tipo do conteúdo. O PHP manda
text/htmlpor padrão; uma API mandariaapplication/json(aula header e Redirecionamento). - (linha em branco)
- Separa o cabeçalho do corpo, que é o HTML.
E com -v (de verbose, "detalhado") você vê os dois lados: as linhas com > são o que o curl mandou (a requisição); as linhas com < são o que ele recebeu:
$ curl -v localhost:8000/loja.php
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:8000...
* connect to ::1 port 8000 from ::1 port 51190 failed: Conexão recusada
* Trying 127.0.0.1:8000...
* Established connection to localhost (127.0.0.1 port 8000) from 127.0.0.1 port 53484
* using HTTP/1.x
> GET /loja.php HTTP/1.1 « a requisição: "me dê /loja.php"
> Host: localhost:8000
> User-Agent: curl/8.18.0 « quem está pedindo (num navegador, o nome dele)
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK « a resposta começa aqui
< Host: localhost:8000
< Date: Fri, 16 Oct 2026 23:49:17 GMT
< Connection: close
< X-Powered-By: PHP/8.5.8
< Content-type: text/html; charset=UTF-8
<
{ [33 bytes data]
* shutting down connection #0
<h1>Lojinha da Ana</h1>
<p>Temos 7 produtos.</p>
As linhas com * são comentários do próprio curl (em inglês). Repare na quinta: o localhost tem dois endereços, ::1 (IPv6) e 127.0.0.1 (IPv4); o curl tentou o primeiro, a conexão foi recusada (o servidor da Ana só escuta no segundo) e ele passou para o outro sozinho. Você não precisa entender cada linha agora; o importante é ver que a requisição é uma mensagem de texto curta e que a resposta é cabeçalho + HTML.
Do lado do servidor
Enquanto isso, no terminal onde o php -S está rodando, o servidor anotou cada visita no seu registro (log):
$ php -S localhost:8000 [Fri Oct 16 20:49:16 2026] PHP 8.5.8 Development Server (http://localhost:8000) started [Fri Oct 16 20:49:17 2026] 127.0.0.1:53466 Accepted « um cliente se conectou [Fri Oct 16 20:49:17 2026] 127.0.0.1:53466 [200]: GET /loja.php « pediu /loja.php; resposta 200 [Fri Oct 16 20:49:17 2026] 127.0.0.1:53466 Closing « conversa encerrada
Cada requisição ocupa três linhas: a conexão aceita, o pedido com o código de resposta e o fechamento. O número depois de 127.0.0.1: muda a cada conexão; é a "porta" do lado do cliente, escolhida ao acaso. (O horário do log está no fuso de Brasília, e o do cabeçalho Date, no de Greenwich: são o mesmo instante.)
Experimente o mesmo arquivo no editor. A caixa está em modo web: ela faz o papel do servidor e do navegador ao mesmo tempo.
Missão: a Ana recebeu mais mercadoria. Troque a conta para 7 + 5 e rode. Depois abra a aba Código-fonte HTML e procure a senha ou o comentário: eles não estão lá.
<?php // Este comentário fica no servidor. $senhaDoBanco = "segredo123"; $produtos = 3 + 4; ?> <h1>Lojinha da Ana</h1> <p>Temos <?= $produtos ?> produtos.</p>
<?php // Este comentário fica no servidor. $senhaDoBanco = "segredo123"; $produtos = 7 + 5; ?> <h1>Lojinha da Ana</h1> <p>Temos <?= $produtos ?> produtos.</p>
PHP no servidor, JavaScript no navegador
Muitos sites usam as duas linguagens juntas, e elas rodam em lugares e momentos diferentes. Veja este arquivo, que tem uma conta em PHP e a mesma conta em JavaScript (o código entre <script> e </script>):
<p>O PHP calculou: <?= 10 * 3 ?></p>
<script>
document.write("O JavaScript calculou: " + (10 * 3));
</script>
O que chega ao navegador:
$ curl localhost:8000/misto.php
<p>O PHP calculou: 30</p> « o PHP já fez a conta
<script>
document.write("O JavaScript calculou: " + (10 * 3)); « o JavaScript chegou intacto
</script>
O PHP rodou no servidor e deixou só o resultado, 30. O código JavaScript, para o PHP, é texto comum: ele passou sem ser tocado. Só depois, no computador de quem visita, o navegador executa o JavaScript e escreve a segunda frase. Por isso:
| PHP | JavaScript (no navegador) | |
|---|---|---|
| Onde roda | No servidor | No computador ou celular de quem visita |
| Quando roda | Antes de a página ser enviada | Depois de a página chegar |
| Quem vê o código | Só quem tem acesso ao servidor | Qualquer visitante (é só abrir o código-fonte) |
| Bom para | Banco de dados, login, senhas, montar o HTML, regras do negócio | Menus, animações, reagir a cliques sem recarregar a página |
| Pode confiar? | Sim: o visitante não consegue mudar o que o PHP faz | Não para segurança: o visitante pode alterar ou desligar o JavaScript |
Depois que a resposta foi enviada, o PHP já terminou. Ele não sabe se o visitante rolou a página ou clicou num botão. Para o PHP fazer algo de novo, o navegador precisa mandar outra requisição: clicar num link, enviar um formulário (aula Formulários HTML) ou o JavaScript pedir dados ao servidor. E toda validação importante (preço, senha, permissões) deve ser feita no PHP, mesmo que o JavaScript também confira: o que roda no navegador pode ser burlado.
Dois jeitos de rodar o PHP: CLI e web
O mesmo PHP pode trabalhar de dois jeitos. Na web, quem chama o PHP é o servidor, a cada requisição. No terminal, quem chama é você, com o comando php. Esse segundo jeito se chama CLI (Command Line Interface, "interface de linha de comando").
O PHP sabe em qual modo está. A constante PHP_SAPI diz o nome do "encaixe" que o chamou (SAPI quer dizer Server API):
<?php echo "Quem está rodando este código: " . PHP_SAPI . "\n";
$ php quem.php « no terminal Quem está rodando este código: cli $ curl localhost:8000/quem.php « pelo servidor embutido Quem está rodando este código: cli-server
O código é o mesmo; quem o chamou, não. No terminal, a SAPI é cli; no servidor embutido, cli-server; num servidor de produção com nginx, seria fpm-fcgi; com o Apache e o módulo do PHP, apache2handler.
E se você rodar a página da lojinha no terminal? O PHP faz o mesmo trabalho e escreve o HTML na tela, com as marcas e tudo, porque o terminal não sabe desenhar HTML:
$ php loja.php <h1>Lojinha da Ana</h1> <p>Temos 7 produtos.</p>
É a mesma saída do curl. Isso mostra uma coisa importante: o PHP não "desenha" páginas, ele só produz texto. Se esse texto vai para o terminal, você vê as marcas; se vai para o navegador, o navegador as transforma em títulos e parágrafos.
CLI (php arquivo.php) | Web (servidor + navegador) | |
|---|---|---|
| Quem chama o PHP | Você, no terminal | O servidor, a cada requisição |
| Para onde vai a saída | A tela do terminal | A resposta HTTP, até o navegador |
| Quebra de linha visível | "\n" | <br> ou <p> (o "\n" vira só um espaço na página) |
| Dados de entrada | Argumentos e teclado ($argv, STDIN) | Endereço e formulários ($_GET, $_POST) |
| Limite de tempo | Nenhum (pode rodar por horas) | 30 segundos por padrão |
| Usado para | Aprender, scripts, tarefas agendadas, ferramentas (Composer, PHPUnit) | Sites, sistemas, APIs |
| No editor do guia | Caixa padrão (saída em texto) | Caixa com data-modo="web" (abas Resultado e Código-fonte) |
O guia usa os dois. As primeiras aulas são quase todas em CLI, porque a saída é mais simples de ler; a partir de PHP Dentro do HTML, o modo web aparece cada vez mais. A aula PHP na Linha de Comando aprofunda o modo CLI.
Quando dá errado
$ curl localhost:8000/loja.php curl: (7) Failed to connect to localhost port 8000 after 0 ms: Could not connect to server
O que aconteceu: não há servidor nenhum escutando na porta 8000. Ninguém (nenhum "garçom") recebeu o pedido. No navegador, a mensagem é "Não é possível acessar esse site" ou "Conexão recusada".
Como resolver: ligue o servidor (php -S localhost:8000) num terminal e deixe-o aberto enquanto testa. Veja O Servidor Embutido.
O que aconteceu: o arquivo chegou ao navegador sem passar pelo PHP. As causas mais comuns: você abriu o arquivo com dois cliques (o endereço começa com file://), o arquivo não termina em .php, ou o servidor web (Apache, nginx) não está configurado para chamar o PHP.
Como resolver: abra pelo endereço do servidor (http://localhost:8000/…) e confira a extensão do arquivo.
O que aconteceu: o PHP lê o arquivo a cada requisição, então a mudança vale na hora, desde que você tenha salvo o arquivo e recarregado a página. Se ainda assim não mudou, o navegador pode estar mostrando uma cópia antiga guardada (o cache).
Como resolver: salve (Ctrl+S), recarregue com Ctrl+Shift+R (recarrega sem usar o cache) e confira se está editando o arquivo da pasta certa: o log do php -S mostra o caminho pedido.
Referência
| Termo | O que é |
|---|---|
| Requisição (request) | O pedido que o navegador manda: método (GET, POST), caminho (/loja.php) e cabeçalhos. |
| Resposta (response) | O que volta: linha de status (200 OK), cabeçalhos e corpo (o HTML). |
| HTTP / HTTPS | A "língua" de navegadores e servidores; o HTTPS é a versão criptografada. |
| Servidor web | O programa que recebe as requisições: Apache, nginx, o php -S. |
localhost | "Este computador". O mesmo que 127.0.0.1 (IPv4) ou ::1 (IPv6). |
| Porta | Um número que separa os serviços de uma máquina. Sites usam 80 (HTTP) e 443 (HTTPS); para testes, usa-se 8000 ou 8080. |
| Código de status | 200 sucesso · 301/302 redirecionamento · 404 não encontrado · 500 erro no servidor. |
| CLI | Rodar o PHP no terminal: php arquivo.php. |
PHP_SAPI | Constante com o modo atual: cli, cli-server, fpm-fcgi, apache2handler. |
curl URL · curl -i · curl -v | Faz a requisição no terminal; mostra só o corpo · com os cabeçalhos da resposta · a conversa inteira. |
Para fechar, veja com os próprios olhos a diferença entre CLI e web. Esta caixa está em modo terminal: ela mostra o texto que o PHP produziu, sem desenhar o HTML.
Missão: rode e veja as marcas <h1> e <p> aparecendo como texto (no terminal ninguém desenha HTML). Depois troque a conta para que a página anuncie Temos 12 produtos.
<?php $produtos = 3 + 4; ?> <h1>Lojinha da Ana</h1> <p>Temos <?= $produtos ?> produtos.</p>
<?php $produtos = 6 + 6; ?> <h1>Lojinha da Ana</h1> <p>Temos <?= $produtos ?> produtos.</p>
Exercícios
1. Coloque na ordem: (a) o PHP executa o arquivo; (b) o navegador desenha a página; (c) o navegador faz a requisição; (d) o servidor devolve o HTML.
2. Um arquivo PHP tem $senha = "abc"; e escreve <p>Oi</p>. O que o visitante vê ao abrir o código-fonte da página?
3. O que o código 404 numa resposta HTTP quer dizer?
4. Onde deve ficar a conferência do preço final de uma compra?
5. O modo do PHP
Que valor echo PHP_SAPI; mostra quando o arquivo é rodado com php arquivo.php no terminal?
Resumo
- Navegador (cliente) faz a requisição; o servidor web recebe; se o arquivo é
.php, o PHP executa; o HTML gerado volta na resposta; o navegador desenha. - O navegador recebe só o HTML: comentários, variáveis e senhas do PHP ficam no servidor. Confira com
curlou "Exibir código-fonte". curl -imostra o cabeçalho da resposta (200 OK,Content-type);curl -vmostra a conversa inteira.- O PHP roda antes de a página ser enviada; o JavaScript, depois que ela chega. Segurança é no PHP.
- O PHP só produz texto. No terminal (CLI,
PHP_SAPI=cli) você vê as marcas; no navegador, a página desenhada. - Próximo passo: Versões do PHP.