Estas são as perguntas de PHP que mais aparecem em entrevistas, com respostas curtas e corretas para o PHP 8.3 e código onde o código mostra o ponto. Tente prever a saída de cada bloco antes de clicar em Run: é isso que um entrevistador testa.
Perguntas de entrevista PHP para iniciantes
O que é PHP e como ele roda?
PHP é uma linguagem de script do lado do servidor. Um servidor web (Nginx ou Apache) passa a requisição para o PHP (normalmente o PHP-FPM), o PHP executa o script do início, e tudo o que ele imprime vira a resposta, normalmente HTML. Cada requisição começa do zero: variáveis não sobrevivem entre requisições, a menos que você as guarde numa sessão, num banco de dados ou num cache. O PHP também roda scripts na linha de comando (php script.php).
Qual a diferença entre == e ===?
== compara depois da conversão de tipos, === compara valor e tipo sem conversão nenhuma. O aquecimento acima mostra o == funcionando: strings numéricas são comparadas como números, então '10' == '1e1' é true. Desde o PHP 8, um número comparado com uma string não numérica é comparado como string, então 0 == 'a' é false (no PHP 7 era true). Toque nas células para comparar os dois operadores:
| $a == $b | true | false | 0 | 1 | "0" | "1" | "" | null | [] | "a" | "10" | "1e1" |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| true | ||||||||||||
| false | ||||||||||||
| 0 | ||||||||||||
| 1 | ||||||||||||
| "0" | ||||||||||||
| "1" | ||||||||||||
| "" | ||||||||||||
| null | ||||||||||||
| [] | ||||||||||||
| "a" | ||||||||||||
| "10" | ||||||||||||
| "1e1" |
Use === por padrão. in_array() e array_search() usam ==, a menos que você passe true como terceiro argumento.
Qual a diferença entre echo e print?
Os dois imprimem strings. O echo recebe vários argumentos (echo $a, $b;) e não retorna nada; o print recebe um e retorna 1, então pode ser usado numa expressão. Nenhum dos dois é função, então os parênteses são opcionais. Na prática, todo mundo usa echo.
Aspas simples ou aspas duplas?
Strings entre aspas duplas interpolam variáveis e sequências de escape: "Hi $name\n". Strings entre aspas simples são literais, exceto por \' e \\: 'Hi $name\n' imprime exatamente esses caracteres. A diferença de velocidade é desprezível, então a escolha é sobre legibilidade: aspas duplas quando você interpola, aspas simples quando não.
Quais são os tipos de dados do PHP?
Quatro tipos escalares (int, float, string, bool), dois compostos (array e object) e dois especiais (null e resource). callable, iterable, mixed e void existem só como declarações de tipo, nunca como o tipo de um valor. gettype() e get_debug_type() dizem o tipo de um valor em tempo de execução, e var_dump() o imprime junto com o valor.
Qual a diferença entre isset, empty e is_null?
isset($x) é true quando a variável existe e não é null. empty($x) é true quando a variável não existe ou é falsa (0, '0', '', [], false, null). is_null($x) é true para null, mas avisa numa variável indefinida. isset e empty nunca avisam, e é por isso que são usados em chaves de array.
| $x | isset | empty | is_null |
|---|---|---|---|
| null | |||
| false | |||
| 0 | |||
| "0" | |||
| "" | |||
| " " | |||
| [] | |||
| "a" | |||
| 0.0 |
A linha que as pessoas erram é a do "0": a string zero é vazia, enquanto " " (um espaço) não é. A página sobre isset tem a tabela completa.
Qual a diferença entre include e require?
Os dois inserem e executam outro arquivo. Se o arquivo não existe, o include emite um aviso e o script continua, enquanto o require lança um Error ("Failed opening required"), que para o script, a menos que algo o capture. As variantes _once (include_once, require_once) pulam um arquivo já carregado, o que evita erros de "cannot redeclare function". Use require (ou require_once) para arquivos sem os quais o script não roda, que são quase todos; o autoloader do Composer torna desnecessária a maioria dos includes manuais.
Qual a diferença entre GET e POST?
O GET envia dados na query string da URL ($_GET), então eles ficam visíveis, podem virar favorito e têm tamanho limitado; use para leitura, como busca e paginação. O POST envia dados no corpo da requisição ($_POST); use para tudo o que altera estado, como login, salvar ou pagamentos. Uma requisição GET nunca deve alterar dados, porque links são pré-carregados e rastreados.
O que é o operador de coalescência nula?
$a ?? $b retorna $a se ele existir e não for null, senão $b, sem aviso para uma variável ou chave indefinida: $page = $_GET['page'] ?? 1;. ??= só atribui quando o lado esquerdo é null ou não existe. Ele difere do ?:, que cai no padrão com qualquer valor falso, então 0 ?: 5 é 5, mas 0 ?? 5 é 0.
Perguntas de entrevista PHP de nível intermediário
O que acontece quando você percorre por referência no foreach?
foreach ($arr as &$v) deixa você alterar os elementos no lugar, mas $v continua sendo uma referência ao último elemento depois do loop. Reutilizar o nome num segundo loop então sobrescreve esse elemento:
O último elemento é 20, não 30: durante o segundo loop, $v (ainda $arr[2]) recebe 10, depois 20, depois ele mesmo. Tire o // antes de unset($v) e rode de novo. A página sobre foreach explica as referências em detalhe.
Qual a diferença entre classe abstrata e interface? E o que é uma trait?
Uma interface é um contrato: assinaturas de métodos (e constantes) sem implementação, e uma classe pode implementar várias. Uma classe abstrata pode ter propriedades, construtores e métodos prontos, mais métodos abstratos que as filhas precisam escrever; uma classe estende só uma. Uma trait é um conjunto de métodos copiados para uma classe com use, para reutilizar código entre classes que não têm uma classe pai em comum.
Uma resposta curta que os entrevistadores gostam: use uma interface para dizer o que algo pode fazer, uma classe abstrata para compartilhar como é feito, e uma trait quando classes sem relação precisam dos mesmos poucos métodos.
Qual a diferença entre self e static?
self se refere à classe onde o código está escrito. static se refere à classe que foi de fato chamada em tempo de execução, o que se chama late static binding. Isso importa em métodos da classe pai que criam ou descrevem "este tipo de objeto":
User::createStatic() cria um User. User::createSelf() cria um Model, o que quebra o tipo de retorno static, então o PHP lança um TypeError. É por isso que métodos de fábrica usam new static().
O que são métodos mágicos?
Métodos que o PHP chama por você, todos começando com dois underscores. Os comuns: __construct() quando um objeto é criado, __destruct() quando é destruído, __toString() quando é usado como string, __get() e __set() para propriedades inacessíveis, __call() e __callStatic() para métodos que não existem, __invoke() quando o objeto é chamado como função, e __clone() depois de um clone.
Qual a diferença entre array_merge() e o operador +?
O array_merge() acrescenta: chaves numéricas são renumeradas e chaves string posteriores sobrescrevem as anteriores. O + é uma união: mantém o array da esquerda e só adiciona as chaves que faltam, então numa chave repetida o primeiro valor vence.
O + é a ferramenta certa para padrões: $options + ['timeout' => 30] mantém o que quem chamou passou e preenche o resto.
O que faz declare(strict_types=1)?
Sem ele, o PHP converte argumentos escalares para o tipo declarado do parâmetro quando consegue: passar "5" para um parâmetro int dá 5. Com declare(strict_types=1); como primeira instrução de um arquivo, as chamadas feitas naquele arquivo precisam passar o tipo exato, senão um TypeError é lançado (um int passado para um parâmetro float é a única ampliação permitida).
Apague a linha do declare e rode de novo: a segunda chamada retorna 10 em vez de lançar um erro.
Qual a diferença entre sessão e cookie?
Um cookie fica guardado no navegador e é enviado em cada requisição, então o visitante pode lê-lo e alterá-lo. Uma sessão guarda os dados no servidor e só mantém um id aleatório num cookie (PHPSESSID). Coloque tudo o que precisa ser confiável, como o id do usuário logado, em $_SESSION; depois do login, chame session_regenerate_id(true). A página sobre sessões e cookies tem o código.
Como evitar SQL injection?
Nunca monte SQL concatenando a entrada. Use prepared statements, para que os valores sejam enviados separados da consulta:
<?php
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
$user = $stmt->fetch();
Marcadores funcionam só para valores. Nomes de tabelas, nomes de colunas e ASC/DESC precisam ser comparados com uma lista permitida antes de entrar no SQL. Veja PDO.
Como evitar XSS?
Escape a saída, não a entrada: envolva todo valor impresso no HTML em htmlspecialchars($value, ENT_QUOTES, 'UTF-8'), ou use um motor de templates que faz isso automaticamente (Twig, Blade). Dentro de <script>, use json_encode() com JSON_HEX_TAG. Adicione um cabeçalho Content-Security-Policy como segunda camada.
Como as senhas devem ser guardadas?
Com password_hash($password, PASSWORD_DEFAULT) e verificadas com password_verify($password, $hash). Eles usam bcrypt (ou Argon2id) com um salt aleatório guardado dentro do hash e um custo proposital. md5() e sha1() são errados para senhas porque são rápidos e sem salt. Use password_needs_rehash() no login para atualizar hashes antigos.
Perguntas de entrevista PHP avançadas
O que são generators e quando você usaria um?
Uma função que contém yield retorna um Generator que produz valores um de cada vez, só quando pedido. Ele permite percorrer uma sequência grande ou infinita sem montar um array na memória:
Usos típicos são ler um arquivo grande linha por linha, transmitir linhas do banco de dados e pipelines preguiçosos. Generators também aceitam chaves (yield $key => $value), delegação (yield from) e recebem valores com send().
O que são closures, e o que faz o use?
Uma função anônima (function () { ... }) é um objeto Closure. Ela não enxerga variáveis de fora, a menos que você as liste no use, que copia o valor no momento em que a closure é criada; use (&$x) captura por referência. Arrow functions (fn ($x) => $x * $factor) capturam variáveis de fora automaticamente, por valor, e contêm uma única expressão.
Qual a diferença entre abstract, final e readonly?
abstract marca uma classe que não pode ser instanciada, ou um método que uma filha precisa implementar. final proíbe sobrescrever um método ou estender uma classe. readonly (PHP 8.1) torna uma propriedade gravável só uma vez, de dentro da classe, normalmente no construtor; o PHP 8.2 adicionou classes readonly, em que todas as propriedades são readonly.
O que é o Composer, e o que é PSR-4?
O Composer é o gerenciador de dependências do PHP: o composer.json lista os pacotes, o composer.lock fixa as versões exatas, e o vendor/autoload.php carrega tudo. O PSR-4 é o padrão de autoload que liga um prefixo de namespace a uma pasta, então App\Mail\Mailer fica em src/Mail/Mailer.php e é carregado no primeiro uso. Explique install (a partir do arquivo lock) e update (novas versões, novo arquivo lock).
O que mudou no PHP 8?
Os principais recursos: no 8.0, argumentos nomeados, match, o operador nullsafe ?->, union types, promoção de propriedades no construtor, atributos, str_contains() e uma comparação mais sensata entre strings e números; no 8.1, enums, propriedades readonly, sintaxe de callable de primeira classe (strlen(...)) e fibers; no 8.2, classes readonly e os tipos avulsos null/true/false; no 8.3, constantes de classe tipadas, o atributo #[\Override] e json_validate(); no 8.4, property hooks, visibilidade assimétrica (public private(set)), array_find() e new Foo()->method() sem parênteses em volta. Muitas funções também passaram a lançar TypeError ou ValueError em vez de retornar false com um aviso.
Como o PHP gerencia a memória?
Todo valor tem uma contagem de referências; quando ela chega a zero, a memória é liberada na hora. Objetos que se referenciam num ciclo nunca chegam a zero, então um coletor de ciclos roda sempre que o buffer de possíveis raízes de ciclo enche (10.000 entradas por padrão) e os libera (gc_collect_cycles() o executa sob demanda). Arrays e strings são copy-on-write: atribuir $b = $a compartilha os dados até que um deles seja modificado. Como cada requisição começa e termina de forma limpa, vazamentos de memória importam mais em workers de longa duração e consumidores de filas.
Como os arrays do PHP são implementados?
Um array PHP é um hash map ordenado: mantém a ordem de inserção e liga chaves int ou string a valores, e é por isso que o mesmo tipo serve como lista, dicionário e pilha. Consultas por chave (isset($arr[$key])) levam tempo constante em média, enquanto o in_array() percorre todos os valores. Chaves string que parecem inteiros são convertidas: $a['1'] e $a[1] são o mesmo elemento.
Tarefas de código comuns em entrevistas
Exercícios curtos muitas vezes pedidos ao vivo. Cada função é uma resposta comum; rode, adicione as suas próprias entradas (incluindo uma vazia) e esteja pronto para explicar a complexidade de tempo, que normalmente é o que o entrevistador está verificando.
Perguntas frequentes
Como me preparo para uma entrevista de desenvolvedor PHP?
Garanta que você consegue explicar e escrever código para o básico sem consultar: comparação e tipos, arrays e suas funções, orientação a objetos (interfaces, classes abstratas, traits, static), exceções e segurança (prepared statements, htmlspecialchars, password_hash). Depois conheça um framework (Laravel ou Symfony) e o Composer bem o bastante para falar sobre um projeto que você construiu.
Qual versão do PHP devo conhecer para uma entrevista?
O PHP 8. Os entrevistadores esperam que você conheça recursos adicionados do 8.0 ao 8.3: argumentos nomeados, match, o operador nullsafe ?->, union types, promoção de propriedades no construtor, enums, propriedades readonly e a sintaxe de callable de primeira classe. Mencione o comportamento do PHP 7 só onde ele mudou, como 0 == "a".
Que perguntas de PHP fazem para iniciantes?
Principalmente o básico da linguagem: == e ===, echo e print, aspas simples e duplas, isset e empty, include e require, GET e POST, sessões e cookies, e tarefas simples com arrays, como inverter, filtrar ou contar valores. Espere pelo menos um exercício curto de código.
Que perguntas de PHP fazem para desenvolvedores experientes?
Design e comportamento por baixo dos panos: interfaces e classes abstratas, traits, late static binding, referências, generators e memória, exceções e tratamento de erros, SQL injection e transações, cache, autoload do Composer e como você estruturaria ou testaria um recurso. Espera-se que as respostas tragam prós e contras, não definições.