</>
GUIA COMPLETO DE
DESENVOLVIMENTO WEB
HTML · PHP · SQL
Do Nível Básico ao Profissional
■ HTML ■ PHP ■ SQL
Estrutura & Layout Lógica & Backend Base de Dados
Criado especialmente para Jorge · SkillTech Academy
2026 · Angola
■ ÍNDICE GERAL
MÓDULO 1 HTML — A Linguagem da Web 03
1.1 O que é HTML e como funciona 03
1.2 Estrutura básica de uma página 04
1.3 Tags essenciais 05
1.4 Formulários e inputs 07
1.5 HTML Semântico (nível avançado) 08
1.6 Tarefas HTML 09
MÓDULO 2 PHP — O Motor do Backend 10
2.1 Introdução ao PHP 10
2.2 Variáveis, tipos e operadores 11
2.3 Condicionais e loops 12
2.4 Funções e arrays 13
2.5 PHP com formulários HTML 15
2.6 PHP Orientado a Objetos 16
2.7 Tarefas PHP 17
MÓDULO 3 SQL — A Linguagem dos Dados 18
3.1 O que é SQL e SGBDs 18
3.2 Criar tabelas e bancos de dados 19
3.3 CRUD — Inserir, Ler, Editar, Deletar 20
3.4 Filtros, ORDER e funções agregadas 22
3.5 JOINs e relacionamentos 23
3.6 Tarefas SQL 24
MÓDULO 4 Integração PHP + MySQL 25
4.1 Ligação PDO ao banco de dados 25
4.2 Sistema de login completo 26
4.3 Projeto Final — Sistema de Cadastro 28
BÓNUS Boas Práticas & Segurança 30
MÓDULO 1
HTML — A Linguagem da Web
■ NÍVEL: BÁSICO
1.1 — O que é HTML?
HTML (HyperText Markup Language) é a linguagem usada para criar e estruturar páginas web. Não
é uma linguagem de programação — é uma linguagem de marcação. Isso significa que usamos tags
(etiquetas) para dizer ao navegador como o conteúdo deve ser apresentado.
■ HTML define O QUÊ aparece na página. CSS define COMO aparece. PHP define O QUE
acontece.
Como o navegador lê HTML:
1. Tu escreves um ficheiro .html no teu computador.
2. O navegador (Chrome, Firefox...) lê esse ficheiro.
3. O navegador interpreta as tags e renderiza a página.
1.2 — Estrutura Básica de uma Página HTML
Toda página HTML segue uma estrutura padrão. Veja abaixo o esqueleto mínimo:
<!DOCTYPE html>
<html lang='pt'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Minha Primeira Página</title>
</head>
<body>
<h1>Olá, Mundo!</h1>
<p>Bem-vindo ao desenvolvimento web.</p>
</body>
</html>
O que cada parte significa:
Tag / Elemento Função
<!DOCTYPE html> Informa ao navegador que é HTML5 (versão mais atual)
<html> Elemento raiz — contém tudo da página
<head> Informações da página (não visíveis ao utilizador)
<meta charset> Define o conjunto de caracteres (UTF-8 suporta acentos)
<title> Título que aparece na aba do navegador
<body> Tudo que é visível na página vai aqui
1.3 — Tags Essenciais do HTML
As tags são a base do HTML. Cada uma tem abertura <tag> e fecho </tag> (algumas são
auto-fechadas, como <img> e <br>).
Títulos e Parágrafos:
<h1>Título Principal</h1> <!-- maior -->
<h2>Subtítulo</h2>
<h3>Secção</h3> <!-- até h6 -->
<p>Este é um parágrafo de texto normal.</p>
<strong>Texto em negrito</strong>
<em>Texto em itálico</em>
<br> <!-- quebra de linha -->
Listas:
<!-- Lista não ordenada (bullets) -->
<ul>
<li>HTML</li>
<li>PHP</li>
<li>SQL</li>
</ul>
<!-- Lista ordenada (números) -->
<ol>
<li>Aprender HTML</li>
<li>Aprender PHP</li>
<li>Aprender SQL</li>
</ol>
Links e Imagens:
<!-- Link para outra página -->
<a href='[Link] aqui</a>
<!-- Link que abre nova aba -->
<a href='[Link] target='_blank'>Abrir no novo separador</a>
<!-- Imagem -->
<img src='[Link]' alt='Descrição da imagem' width='300'>
Tabelas:
<table border='1'>
<thead>
<tr>
<th>Nome</th>
<th>Idade</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jorge</td>
<td>19</td>
</tr>
</tbody>
</table>
1.4 — Formulários e Inputs
Formulários permitem ao utilizador enviar dados para o servidor. São a base da comunicação entre o
HTML e o PHP.
<form action='[Link]' method='POST'>
<label for='nome'>O teu nome:</label>
<input type='text' id='nome' name='nome' placeholder='Ex: Jorge' required>
<label for='email'>E-mail:</label>
<input type='email' id='email' name='email' required>
<label for='senha'>Senha:</label>
<input type='password' id='senha' name='senha' minlength='6'>
<label for='nivel'>Nível:</label>
<select id='nivel' name='nivel'>
<option value='basico'>Básico</option>
<option value='avancado'>Avançado</option>
</select>
<textarea name='mensagem' rows='4' placeholder='Escreve aqui...'></textarea>
<button type='submit'>Enviar</button>
</form>
■ method='POST' envia dados de forma segura (não visível na URL). method='GET' envia
dados na URL (visível).
■ NÍVEL: AVANÇADO
1.5 — HTML Semântico
HTML semântico significa usar as tags certas para o conteúdo certo. Melhora a acessibilidade e o
SEO (posicionamento no Google).
<header>
<nav>
<ul>
<li><a href='/'>Início</a></li>
<li><a href='/sobre'>Sobre</a></li>
</ul>
</nav>
</header>
<main>
<section id='hero'>
<article>
<h2>Artigo Principal</h2>
<p>Conteúdo do artigo...</p>
</article>
</section>
</main>
<aside>Barra lateral</aside>
<footer>© 2026 SkillTech</footer>
1.6 — ■ Tarefas HTML
✏ TAREFA 01 — A Tua Primeira Página
• Cria um ficheiro chamado [Link]
• Adiciona: título da página (na aba), um <h1> com o teu nome, um parágrafo sobre ti
• Adiciona uma lista com 3 tecnologias que queres aprender
• Adiciona um link para o site da SkillTech (ou qualquer URL)
• Desafio extra: Adiciona uma imagem ao lado do teu nome
✏ TAREFA 02 — Página com Tabela e Formulário
• Cria uma página com uma tabela de 3 colunas: Nome, Produto, Preço
• Adiciona pelo menos 4 linhas de dados fictícios
• Abaixo da tabela, cria um formulário de contacto com: nome, email, mensagem e botão
enviar
• O formulário deve usar method='POST' e action='[Link]'
• Desafio extra: Adiciona validação HTML5 (required, type='email', minlength)
✏ TAREFA 03 — Layout Semântico Completo [AVANÇADO]
• Constrói uma página completa usando: <header>, <nav>, <main>, <section>, <aside>,
<footer>
• O <nav> deve ter pelo menos 4 links de navegação
• O <main> deve ter 2 <article> com título e parágrafo cada
• O <aside> deve ter uma lista de 'Links Úteis'
• Dica: Usa o validador: [Link] para verificar o teu código
MÓDULO 2
PHP — O Motor do Backend
■ NÍVEL: BÁSICO
2.1 — Introdução ao PHP
PHP (Hypertext Preprocessor) é uma linguagem de programação do lado do servidor. Enquanto o
HTML é estático (sempre igual), o PHP gera conteúdo dinâmico — pode ler dados de uma base de
dados, processar formulários, fazer login de utilizadores, etc.
■ PHP corre no servidor. O utilizador só vê o HTML gerado — nunca vê o código PHP.
O teu primeiro script PHP:
<?php
// Todo código PHP começa com <?php e termina com ?>
echo 'Olá, Jorge! Bem-vindo ao PHP.';
// Podes misturar PHP com HTML:
$nome = 'Jorge';
echo '<h1>Bem-vindo, ' . $nome . '!</h1>';
?>
Como instalar PHP localmente:
• XAMPP (Windows/Mac/Linux) — recomendado para iniciantes: inclui PHP + MySQL + Apache
• Laragon (Windows) — mais moderno e rápido
• Coloca os teus ficheiros .php na pasta htdocs do XAMPP
• Acede em: [Link]
2.2 — Variáveis, Tipos e Operadores
<?php
// ■■ VARIÁVEIS ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// Em PHP, variáveis começam sempre com $
$nome = 'Jorge'; // String (texto)
$idade = 19; // Integer (número inteiro)
$altura = 1.75; // Float (número decimal)
$ativo = true; // Boolean (verdadeiro/falso)
$nulo = null; // Nulo (sem valor)
// ■■ EXIBIR VARIÁVEIS ■■■■■■■■■■■■■■■■■■■■■■■■■■■
echo $nome; // Imprime: Jorge
echo 'Idade: ' . $idade; // Concatenar strings com ponto (.)
echo "Altura: $altura m"; // Aspas duplas interpolam variáveis
// ■■ OPERADORES ARITMÉTICOS ■■■■■■■■■■■■■■■■■■■■■
$soma = 10 + 5; // 15
$subtracao = 10 - 3; // 7
$divisao = 20 / 4; // 5
$resto = 10 % 3; // 1 (módulo/resto)
$potencia = 2 ** 8; // 256
// ■■ COMPARAÇÕES ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
var_dump(10 == '10'); // true (valor igual)
var_dump(10 === '10'); // false (tipo diferente!)
var_dump(10 !== 5); // true
var_dump(10 > 5); // true
?>
2.3 — Condicionais e Loops
<?php
// ■■ IF / ELSE IF / ELSE ■■■■■■■■■■■■■■■■■■■■■■■■
$nota = 85;
if ($nota >= 90) {
echo 'Excelente!';
} elseif ($nota >= 70) {
echo 'Bom trabalho!'; // <-- esta linha executa
} elseif ($nota >= 50) {
echo 'Suficiente';
} else {
echo 'Reprovado';
}
// ■■ SWITCH ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
$dia = 'segunda';
switch ($dia) {
case 'segunda': echo 'Início da semana'; break;
case 'sexta': echo 'Quase fim!'; break;
default: echo 'Dia normal';
}
// ■■ LOOP FOR ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
for ($i = 1; $i <= 5; $i++) {
echo "Número: $i <br>";
}
// ■■ LOOP WHILE ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
$contador = 0;
while ($contador < 3) {
echo "Contagem: $contador <br>";
$contador++;
}
// ■■ FOREACH (para arrays) ■■■■■■■■■■■■■■■■■■■■■■■
$frutas = ['banana', 'manga', 'maçã'];
foreach ($frutas as $fruta) {
echo "Fruta: $fruta <br>";
}
?>
2.4 — Funções e Arrays
<?php
// ■■ FUNÇÕES ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
function saudar($nome, $hora = 'dia') {
return "Bom $hora, $nome!";
}
echo saudar('Jorge'); // Bom dia, Jorge!
echo saudar('SkillTech', 'tarde'); // Bom tarde, SkillTech!
// ■■ ARRAYS SIMPLES ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
$tecnologias = ['HTML', 'PHP', 'SQL', 'JavaScript'];
echo $tecnologias[0]; // HTML (índices começam no 0)
echo count($tecnologias); // 4
echo implode(', ', $tecnologias); // HTML, PHP, SQL, JavaScript
// ■■ ARRAYS ASSOCIATIVOS (chave => valor) ■■■■■■■■
$utilizador = [
'nome' => 'Jorge',
'idade' => 19,
'pais' => 'Angola',
];
echo $utilizador['nome']; // Jorge
// ■■ FUNÇÕES ÚTEIS DE STRING ■■■■■■■■■■■■■■■■■■■■■
$texto = ' Olá Mundo ';
echo strtoupper($texto); // OLÁ MUNDO
echo strtolower($texto); // olá mundo
echo trim($texto); // Remove espaços das pontas
echo strlen('Jorge'); // 5 (comprimento)
echo str_replace('Mundo','PHP','Olá Mundo'); // Olá PHP
?>
■ NÍVEL: INTERMÉDIO
2.5 — PHP com Formulários HTML
Um dos usos mais comuns do PHP é processar formulários HTML. Veja como criar um formulário de
contacto completo:
[Link] — O Formulário:
<form action='[Link]' method='POST'>
<input type='text' name='nome' placeholder='O teu nome' required>
<input type='email' name='email' placeholder='O teu email' required>
<textarea name='mensagem' placeholder='Mensagem'></textarea>
<button type='submit'>Enviar</button>
</form>
[Link] — O PHP que recebe os dados:
<?php
// Verificar se o formulário foi enviado
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Receber e limpar os dados (SEGURANÇA!)
$nome = htmlspecialchars(trim($_POST['nome']));
$email = htmlspecialchars(trim($_POST['email']));
$mensagem = htmlspecialchars(trim($_POST['mensagem']));
// Validar
if (empty($nome) || empty($email)) {
echo 'Erro: Nome e email são obrigatórios!';
exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo 'Erro: Email inválido!';
exit;
}
// Usar os dados
echo "<h2>Mensagem recebida!</h2>";
echo "<p>Nome: $nome</p>";
echo "<p>Email: $email</p>";
echo "<p>Mensagem: $mensagem</p>";
}
?>
■ NÍVEL: AVANÇADO
2.6 — PHP Orientado a Objetos (POO)
POO organiza o código em classes e objetos. É essencial para projetos grandes como a
SkillWallet.
<?php
// ■■ DEFINIR CLASSE ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
class Utilizador {
// Propriedades
private string $nome;
private string $email;
private int $pontos = 0;
// Construtor — executado ao criar o objeto
public function __construct(string $nome, string $email) {
$this->nome = $nome;
$this->email = $email;
}
// Métodos
public function adicionarPontos(int $quantidade): void {
$this->pontos += $quantidade;
}
public function getPerfil(): string {
return "$this->nome | $this->email | Pontos: $this->pontos";
}
}
// ■■ HERANÇA ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
class Admin extends Utilizador {
public function banirUtilizador(string $alvo): string {
return "Admin baniu: $alvo";
}
}
// ■■ USAR AS CLASSES ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
$jorge = new Utilizador('Jorge', 'jorge@[Link]');
$jorge->adicionarPontos(150);
echo $jorge->getPerfil();
// Jorge | jorge@[Link] | Pontos: 150
?>
2.7 — ■ Tarefas PHP
✏ TAREFA 04 — Calculadora Básica
• Cria um formulário HTML com dois campos numéricos e um selector de operação (+, -, *, /)
• O PHP deve receber os valores e calcular o resultado
• Exibe o resultado formatado: '10 + 5 = 15'
• Trata a divisão por zero com uma mensagem de erro adequada
• Desafio extra: Adiciona a operação de potência (2 ** 8 = 256)
✏ TAREFA 05 — Gerador de Tabuada
• Cria uma função PHP chamada tabuada($numero)
• A função deve retornar um array com os resultados de 1 a 10
• Exibe a tabuada numa tabela HTML formatada
• Cria um formulário que recebe o número e chama a função
• Desafio extra: Permite gerar tabuadas de 1 a 10 ao mesmo tempo numa só página
✏ TAREFA 06 — Sistema de Login Simples [AVANÇADO]
• Cria um array associativo com 3 utilizadores (nome, email, senha)
• Faz um formulário de login com email e senha
• O PHP verifica se o email e a senha correspondem a algum utilizador do array
• Se correto: mostra 'Bem-vindo, [Nome]!' e o perfil do utilizador
• Se errado: mostra mensagem de erro e volta ao formulário
• DICA: Usa password_hash() para guardar senhas de forma segura
MÓDULO 3
SQL — A Linguagem dos Dados
■ NÍVEL: BÁSICO
3.1 — O que é SQL?
SQL (Structured Query Language) é a linguagem padrão para comunicar com bases de dados
relacionais. Com SQL podes criar, ler, actualizar e apagar dados — operações conhecidas como
CRUD.
SGBD Uso Comum Gratuito?
MySQL / MariaDB Web (WordPress, PHP apps) ■ Sim
PostgreSQL Apps empresariais e IA ■ Sim
SQLite Apps móveis, protótipos ■ Sim
SQL Server Sistemas Windows/Microsoft ■ Parcial
Oracle DB Grandes empresas ■ Pago
■ Vamos usar MySQL neste curso — é o mais usado com PHP e é gratuito.
3.2 — Criar Base de Dados e Tabelas
-- Criar uma base de dados
CREATE DATABASE skilltech_db;
-- Selecionar para usar
USE skilltech_db;
-- Criar tabela de utilizadores
CREATE TABLE utilizadores (
id INT AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE NOT NULL,
senha VARCHAR(255) NOT NULL,
pontos INT DEFAULT 0,
ativo BOOLEAN DEFAULT TRUE,
criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Criar tabela de produtos
CREATE TABLE produtos (
id INT AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(200) NOT NULL,
preco DECIMAL(10,2) NOT NULL,
stock INT DEFAULT 0,
categoria VARCHAR(100),
criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Tipos de dados mais usados:
Tipo Descrição Exemplo
INT Número inteiro idade INT
VARCHAR(n) Texto com limite de n caracteres nome VARCHAR(100)
TEXT Texto longo sem limite descricao TEXT
DECIMAL(m,d) Número com casas decimais preco DECIMAL(10,2)
BOOLEAN Verdadeiro ou falso ativo BOOLEAN
DATE Data (ano-mês-dia) nascimento DATE
TIMESTAMP Data e hora automáticas criado_em TIMESTAMP
3.3 — CRUD — As 4 Operações Fundamentais
C — CREATE (Inserir dados):
-- Inserir um registo
INSERT INTO utilizadores (nome, email, senha, pontos)
VALUES ('Jorge Silva', 'jorge@[Link]', 'hash123', 100);
-- Inserir múltiplos registos de uma vez
INSERT INTO produtos (nome, preco, stock, categoria) VALUES
('Smartphone X', 450.00, 15, 'Electrónica'),
('Laptop Pro', 1200.00, 5, 'Informática'),
('Tablet Mini', 350.00, 20, 'Electrónica');
R — READ (Ler/Consultar dados):
-- Buscar todos os utilizadores
SELECT * FROM utilizadores;
-- Buscar colunas específicas
SELECT nome, email, pontos FROM utilizadores;
-- Com condição WHERE
SELECT * FROM utilizadores WHERE pontos > 50;
-- Buscar um registo pelo ID
SELECT * FROM utilizadores WHERE id = 1;
-- Buscar por texto parcial (LIKE)
SELECT * FROM produtos WHERE nome LIKE '%Laptop%';
-- Limitar resultados
SELECT * FROM produtos LIMIT 10;
-- Contar registos
SELECT COUNT(*) AS total FROM utilizadores;
U — UPDATE (Actualizar dados):
-- Actualizar um campo
UPDATE utilizadores SET pontos = 200 WHERE id = 1;
-- Actualizar múltiplos campos
UPDATE utilizadores
SET nome = 'Jorge Santos', email = '[Link]@[Link]'
WHERE id = 1;
-- Incrementar valor
UPDATE produtos SET stock = stock - 1 WHERE id = 3;
-- ■ ATENÇÃO: Sem WHERE, actualiza TODOS os registos!
-- UPDATE utilizadores SET pontos = 0; -- NÃO FAÇAS ISTO SEM WHERE!
D — DELETE (Apagar dados):
-- Apagar um registo específico
DELETE FROM utilizadores WHERE id = 5;
-- Apagar com condição
DELETE FROM produtos WHERE stock = 0;
-- Apagar todos os registos (mantém a tabela)
TRUNCATE TABLE logs_antigos;
-- Apagar a tabela inteira
DROP TABLE IF EXISTS tabela_temporaria;
-- ■ ATENÇÃO: DELETE sem WHERE apaga TUDO!
■ NÍVEL: INTERMÉDIO
3.4 — Filtros, Ordenação e Funções Agregadas
-- ORDER BY — ordenar resultados
SELECT * FROM produtos ORDER BY preco ASC; -- crescente
SELECT * FROM produtos ORDER BY preco DESC; -- decrescente
-- WHERE com múltiplas condições
SELECT * FROM produtos
WHERE preco > 100 AND categoria = 'Electrónica';
SELECT * FROM utilizadores
WHERE pontos < 50 OR ativo = FALSE;
-- BETWEEN — valores num intervalo
SELECT * FROM produtos WHERE preco BETWEEN 100 AND 500;
-- IN — lista de valores
SELECT * FROM produtos WHERE categoria IN ('Electrónica', 'Informática');
-- ■■ FUNÇÕES AGREGADAS ■■■■■■■■■■■■■■■■■■■■■■■■■■■■
SELECT COUNT(*) AS total_produtos FROM produtos;
SELECT SUM(preco) AS valor_total FROM produtos;
SELECT AVG(preco) AS preco_medio FROM produtos;
SELECT MAX(preco) AS mais_caro FROM produtos;
SELECT MIN(preco) AS mais_barato FROM produtos;
-- GROUP BY — agrupar por categoria
SELECT categoria, COUNT(*) AS quantidade, AVG(preco) AS media
FROM produtos
GROUP BY categoria
HAVING COUNT(*) > 1; -- filtro APÓS o agrupamento
■ NÍVEL: AVANÇADO
3.5 — JOINs e Relacionamentos
JOINs permitem combinar dados de múltiplas tabelas relacionadas. É um dos conceitos mais
importantes do SQL avançado.
-- Tabela de pedidos (referencia utilizadores e produtos)
CREATE TABLE pedidos (
id INT AUTO_INCREMENT PRIMARY KEY,
utilizador_id INT NOT NULL,
produto_id INT NOT NULL,
quantidade INT DEFAULT 1,
data_pedido TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (utilizador_id) REFERENCES utilizadores(id),
FOREIGN KEY (produto_id) REFERENCES produtos(id)
);
-- ■■ INNER JOIN — só registos com correspondência ■■
SELECT [Link], [Link] AS produto, [Link]
FROM pedidos pe
INNER JOIN utilizadores u ON pe.utilizador_id = [Link]
INNER JOIN produtos p ON pe.produto_id = [Link];
-- ■■ LEFT JOIN — todos os utilizadores, mesmo sem pedidos ■■
SELECT [Link], COUNT([Link]) AS total_pedidos
FROM utilizadores u
LEFT JOIN pedidos pe ON [Link] = pe.utilizador_id
GROUP BY [Link], [Link]
ORDER BY total_pedidos DESC;
-- ■■ Subconsulta (subquery) ■■■■■■■■■■■■■■■■■■■■■■
SELECT * FROM utilizadores
WHERE id IN (
SELECT DISTINCT utilizador_id FROM pedidos
WHERE data_pedido >= '2026-01-01'
);
3.6 — ■ Tarefas SQL
✏ TAREFA 07 — Criar e Popular uma Base de Dados
• Cria uma base de dados chamada loja_angola
• Cria as tabelas: clientes (id, nome, email, telefone, cidade) e vendas (id, cliente_id, valor,
data)
• Insere pelo menos 5 clientes angolanos com cidades reais (Luanda, Huambo, Benguela...)
• Insere pelo menos 8 vendas com valores e datas variados
• Faz um SELECT para ver todos os dados de cada tabela
✏ TAREFA 08 — Consultas e Filtros
• Lista todas as vendas acima de 50,000 Kz ordenadas por valor decrescente
• Conta quantos clientes existem por cidade
• Calcula o valor total e médio de todas as vendas
• Lista os 3 clientes com maior número de compras (usando JOIN + GROUP BY)
• Desafio extra: Lista clientes que NUNCA fizeram uma compra (LEFT JOIN + IS NULL)
✏ TAREFA 09 — Actualizar e Gerir Dados [AVANÇADO]
• Actualiza o telefone de um cliente específico pelo ID
• Apaga todas as vendas com valor abaixo de 1,000 Kz
• Adiciona uma coluna 'desconto DECIMAL(5,2) DEFAULT 0.00' à tabela vendas
• Cria uma VIEW chamada 'vendas_com_clientes' que combina as duas tabelas
• Desafio extra: Cria um INDEX na coluna email da tabela clientes e explica para que serve
MÓDULO 4
PHP + MySQL — A Combinação Profissional
■ NÍVEL: PROFISSIONAL
4.1 — Conectar PHP ao MySQL com PDO
PDO (PHP Data Objects) é a forma moderna e segura de conectar PHP a bases de dados. É
preferível ao antigo mysql_connect() e protege contra SQL Injection.
<?php
// ■■ FICHEIRO: config/[Link] ■■■■■■■■■■■■■■■
define('DB_HOST', 'localhost');
define('DB_NAME', 'skilltech_db');
define('DB_USER', 'root');
define('DB_PASS', ''); // Muda em produção!
define('DB_CHAR', 'utf8mb4');
function getConnection(): PDO {
$dsn = 'mysql:host=' . DB_HOST .
';dbname=' . DB_NAME .
';charset=' . DB_CHAR;
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
return new PDO($dsn, DB_USER, DB_PASS, $options);
} catch (PDOException $e) {
die('Erro de ligação: ' . $e->getMessage());
}
}
// ■■ USAR A LIGAÇÃO ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
$pdo = getConnection();
// Query segura com prepared statement (previne SQL Injection)
$stmt = $pdo->prepare('SELECT * FROM utilizadores WHERE email = :email');
$stmt->execute([':email' => 'jorge@[Link]']);
$utilizador = $stmt->fetch();
if ($utilizador) {
echo 'Bem-vindo, ' . $utilizador['nome'];
} else {
echo 'Utilizador não encontrado.';
}
?>
4.2 — Sistema de Login Completo
Este é um sistema de login profissional com sessões PHP e senhas com hash seguro.
[Link] — Logica PHP:
<?php
session_start();
require_once 'config/[Link]';
if (isset($_SESSION['user_id'])) {
header('Location: [Link]'); exit;
}
$erro = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
$senha = trim($_POST['senha'] ?? '');
if (empty($email) || empty($senha)) {
$erro = 'Preenche todos os campos!';
} else {
$pdo = getConnection();
$stmt = $pdo->prepare(
'SELECT id, nome, senha FROM utilizadores WHERE email = :email AND ativo =
1'
);
$stmt->execute([':email' => $email]);
$user = $stmt->fetch();
if ($user && password_verify($senha, $user['senha'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_nome'] = $user['nome'];
header('Location: [Link]'); exit;
} else { $erro = 'Email ou senha incorretos!'; }
}
}
?>
[Link] — HTML do formulario:
<!DOCTYPE html>
<html><head><title>Login</title></head>
<body>
<h2>Entrar na SkillTech</h2>
<?php if($erro): ?>
<p style='color:red'><?= htmlspecialchars($erro) ?></p>
<?php endif; ?>
<form method='POST'>
<input type='email' name='email' placeholder='Email' required>
<input type='password' name='senha' placeholder='Senha' required>
<button type='submit'>Entrar</button>
</form>
</body></html>
4.3 — Projecto Final: Sistema de Cadastro de Produtos
Este projecto integra HTML, PHP e MySQL num sistema CRUD completo:
-- Estrutura recomendada do projecto:
projeto/
■■■ config/
■ ■■■ [Link] (ligação PDO)
■■■ produtos/
■ ■■■ [Link] (READ — lista todos)
■ ■■■ [Link] (CREATE — formulário + inserir)
[Link] (UPDATE - formulario + actualizar)
[Link] (DELETE - confirmacao + apagar)
■■■ css/
■ ■■■ [Link] (estilos da aplicação)
■■■ [Link] (página principal — redireciona)
produtos/[Link] — Criar produto:
<?php
require_once '../config/[Link]';
$pdo = getConnection();
$erro = $sucesso = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$nome = trim($_POST['nome'] ?? '');
$preco = (float)($_POST['preco'] ?? 0);
$stock = (int)($_POST['stock'] ?? 0);
if (empty($nome) || $preco <= 0) {
$erro = 'Nome e preço são obrigatórios!';
} else {
$sql = 'INSERT INTO produtos (nome, preco, stock) VALUES (:nome, :preco, :sto
ck)';
$stmt = $pdo->prepare($sql);
$stmt->execute([':nome'=>$nome, ':preco'=>$preco, ':stock'=>$stock]);
$sucesso = 'Produto criado com ID: ' . $pdo->lastInsertId();
}
}
?>
...
<form method='POST'>
<input type='text' name='nome' placeholder='Nome do produto' required>
<input type='number' name='preco' placeholder='Preço (Kz)' step='0.01' required>
<input type='number' name='stock' placeholder='Stock' value='0'>
<button type='submit'>Guardar Produto</button>
</form>
✏ TAREFA 10 — PROJECTO FINAL — Sistema CRUD Completo
• Constrói um sistema completo de gestão de produtos com PHP + MySQL
• Implementa as 4 operações: Listar, Criar, Editar e Apagar produtos
• Adiciona paginação na listagem (10 produtos por página)
• Adiciona um campo de pesquisa por nome de produto
• Protege todas as acções com sessão (utilizador tem de estar logado)
• Desafio PROFISSIONAL: Adiciona upload de imagem para os produtos
• Dica: Usa Bootstrap ou Tailwind para deixar o design profissional
BÓNUS
Boas Práticas & Segurança Web
■ NÍVEL: PROFISSIONAL
■ Segurança — Os 5 Mandamentos do Dev Web
■ 1. Nunca confies em dados do utilizador: Tudo que vem de $_POST, $_GET ou $_COOKIE
pode estar adulterado. Valida e sanitiza SEMPRE.
■ 2. Usa Prepared Statements: NUNCA concatenes variáveis directamente em queries SQL.
Usa sempre PDO com :parametros.
■ 3. Guarda senhas com hash: NUNCA guardes senhas em texto simples. Usa
password_hash() e password_verify() no PHP.
■ 4. Protege contra XSS: Usa htmlspecialchars() ao exibir dados vindos do utilizador no HTML.
■ 5. Usa HTTPS em produção: Todos os dados devem trafegar encriptados. Serviços como
Let's Encrypt dão certificados grátis.
Checklist de Segurança:
■ Usar prepared statements (PDO) em todas as queries
■ Validar e sanitizar todos os inputs do utilizador
■ Usar password_hash() para guardar senhas
■ Usar session_regenerate_id() após login
■ Definir httponly e secure nos cookies de sessão
■ Usar HTTPS em produção
■ Nunca exibir erros de PHP em produção (display_errors = Off)
■ Usar CSRF tokens nos formulários
■ Fazer backup regular da base de dados
■ Manter PHP e MySQL actualizados
■ Estrutura de Projecto Profissional
meu_projeto/
■■■ app/
■ ■■■ controllers/ (lógica de negócio)
■ ■■■ models/ (acesso à base de dados)
■ ■■■ views/ (templates HTML)
■■■ config/
■ ■■■ [Link] (configuração PDO)
■ ■■■ [Link] (constantes globais)
■■■ public/ (única pasta acessível pelo browser)
■ ■■■ [Link] (ponto de entrada)
■ ■■■ css/
■ ■■■ js/
■ ■■■ images/
■■■ vendor/ (dependências — Composer)
■■■ .env (variáveis de ambiente — NÃO no Git!)
■■■ .gitignore
■■■ [Link]
■ Próximos Passos — Roadmap do Dev Web
Nível 1 — Concluído ■ HTML + PHP + SQL Básico
Nível 2 — CSS
Avançado Flexbox, Grid, Animações, Tailwind CSS
Nível 3 — JavaScript DOM, Fetch API, JSON, React/Vue
Nível 4 — Framework
PHP Laravel ou Symfony — MVC profissional
Nível 5 — DevOps Git, Docker, CI/CD, AWS/VPS, HTTPS
■ Mensagem Final
Jorge, aprender HTML, PHP e SQL é a base sólida de qualquer programador web. Não te apresses
— pratica cada conceito, faz todos os exercícios e constrói projectos reais. A SkillWallet que estás a
construir usa exactamente estes fundamentos no seu backend. Cada linha de código que escreves
hoje é um tijolo na tua carreira profissional. Continua a construir!
SkillTech Academy · 2026 Guia HTML + PHP + SQL Do Básico ao Profissional