Projeto Prático — Matrizes e Funções
Você passou 14 aulas aprendendo sobre sintaxe e funções. Agora é hora de juntar tudo isso. Esses três projetos — que vão do simples ao ambicioso — permitirão que você crie aplicativos PHP reais e executáveis.
1. Configuração
Crie uma pasta practice/ dentro do diretório htdocs/myphp/ e coloque todos os seus arquivos de exercícios lá. Acesse-os em http://localhost/myphp/practice/.
2. Projeto Um: Carrinho de compras
Modele um carrinho de compras usando uma matriz — adicione itens, atualize quantidades, remova itens e calcule os totais.
<?php
// cart.php — Shopping Cart System
/**
* Add an item to the cart
* @param array $cart Cart array (by reference)
* @param string $name Product name
* @param float $price Unit price
* @param int $qty Quantity (default: 1)
* @return void
*/
function addItem(array &$cart, string $name, float $price, int $qty = 1): void {
if (isset($cart[$name])) {
$cart[$name]['qty'] += $qty;
} else {
$cart[$name] = ['price' => $price, 'qty' => $qty];
}
}
/**
* Update a product's quantity
*/
function updateQty(array &$cart, string $name, int $qty): void {
if ($qty <= 0) {
unset($cart[$name]);
} elseif (isset($cart[$name])) {
$cart[$name]['qty'] = $qty;
}
}
/**
* Remove an item from the cart
*/
function removeItem(array &$cart, string $name): void {
unset($cart[$name]);
}
/**
* Calculate the total price
*/
function getTotal(array $cart): float {
return array_sum(array_map(
fn($item) => $item['price'] * $item['qty'],
$cart
));
}
// === Test the cart ===
$cart = [];
addItem($cart, "PHP Tutorial", 39.90, 2);
addItem($cart, "MySQL Basics", 29.90, 1);
addItem($cart, "PHP Tutorial", 39.90, 1); // Add one more copy
echo "<pre>";
echo "Cart contents:\n";
print_r($cart);
echo "\nTotal: $" . getTotal($cart) . "\n";
// Update quantity
updateQty($cart, "MySQL Basics", 3);
echo "\nAfter update — Total: $" . getTotal($cart) . "\n";
// Remove an item
removeItem($cart, "PHP Tutorial");
echo "\nAfter removal:\n";
print_r($cart);
echo "\nFinal total: $" . getTotal($cart) . "\n";
echo "</pre>";
?>
3. Projeto 2: Lista de tarefas
Gerencie tarefas com uma matriz — adicione, conclua, exclua, filtre por status e classifique por prioridade.
▶ Exemplo: Aplicativo de tarefas
<?php
// todo.php — To-Do List
/**
* Add a new task
*/
function addTodo(array &$todos, string $title, string $priority = "medium"): void {
$todos[] = [
'id' => count($todos) + 1,
'title' => $title,
'done' => false,
'priority' => $priority,
'created' => date("Y-m-d H:i:s"),
];
}
/**
* Mark a task as complete
*/
function markDone(array &$todos, int $id): void {
foreach ($todos as &$todo) {
if ($todo['id'] === $id) {
$todo['done'] = true;
break;
}
}
}
/**
* Delete a task
*/
function deleteTodo(array &$todos, int $id): void {
$todos = array_filter($todos, fn($t) => $t['id'] !== $id);
}
/**
* Get all pending (incomplete) tasks
*/
function getPending(array $todos): array {
return array_filter($todos, fn($t) => !$t['done']);
}
/**
* Completion statistics
*/
function getStats(array $todos): array {
$total = count($todos);
$done = count(array_filter($todos, fn($t) => $t['done']));
return ['total' => $total, 'done' => $done, 'pending' => $total - $done];
}
// === Test the Todo app ===
$todos = [];
addTodo($todos, "Learn PHP arrays", "high");
addTodo($todos, "Practice foreach loops", "medium");
addTodo($todos, "Write the cart functions", "high");
addTodo($todos, "Review date functions", "low");
markDone($todos, 1);
markDone($todos, 3);
$stats = getStats($todos);
echo "Total: {$stats['total']} | Done: {$stats['done']} | Pending: {$stats['pending']}<br>";
echo "<h3>Pending Tasks</h3>";
foreach (getPending($todos) as $todo) {
$priorityEmoji = [
'high' => '🔴',
'medium' => '🟡',
'low' => '🟢',
];
echo $priorityEmoji[$todo['priority']] . " {$todo['title']}<br>";
}
?>
4. Projeto Três: Enquete Simples
Use um array associativo para armazenar opções e contagens de votos, com suporte para votação, visualização de resultados e classificação por votos.
▶ Exemplo: Sistema de votação
<?php
// vote.php — Simple Poll
function createPoll(array $options): array {
return array_fill_keys($options, 0);
}
function vote(array &$poll, string $option): bool {
if (!array_key_exists($option, $poll)) {
return false;
}
$poll[$option]++;
return true;
}
function getResults(array $poll): array {
arsort($poll); // Sort by vote count descending
return $poll;
}
function getTotalVotes(array $poll): int {
return array_sum($poll);
}
function getWinner(array $poll): ?string {
$results = getResults($poll);
$maxVotes = max($results);
if ($maxVotes === 0) return null;
return array_key_first($results);
}
// === Test the poll ===
$poll = createPoll(["PHP", "Python", "JavaScript", "Go", "Rust"]);
vote($poll, "PHP");
vote($poll, "PHP");
vote($poll, "JavaScript");
vote($poll, "Python");
vote($poll, "PHP");
vote($poll, "Rust");
vote($poll, "Python");
echo "<h3>Poll Results</h3>";
echo "Total votes: " . getTotalVotes($poll) . "<br>";
$results = getResults($poll);
foreach ($results as $lang => $votes) {
$percent = round($votes / getTotalVotes($poll) * 100, 1);
$bar = str_repeat("█", $votes);
echo "{$lang}: {$bar} {$votes} vote(s) ({$percent}%)<br>";
}
echo "<br>🏆 Leader: " . getWinner($poll) . "<br>";
?>
5. Reflexão: Dos scripts às aplicações
Esses três projetos ilustram várias ideias fundamentais:
- Matrizes não servem apenas para armazenar dados — elas podem modelar a lógica de negócios real.
- Funções encapsulam operações para que seu código permaneça limpo e modular.
- Passagem por referência (
&$arr) permite que as funções modifiquem estruturas de dados diretamente. array_map+ funções-seta tornam o processamento de dados conciso e legível.
Mas você provavelmente também já percebeu as limitações:
- Todos os dados ficam na memória — eles desaparecem quando a página é atualizada. (Resolvido posteriormente com sessões/bancos de dados.)
- O código e a apresentação estão misturados. (Problema resolvido posteriormente com a arquitetura MVC.)
- Ainda não há interação com formulários. (Isso será abordado na próxima aula.)
❓ Perguntas Frequentes
P: Por que usar um array associativo para o carrinho em vez de um indexado? R: Os arrays associativos usam o nome do produto como chave, permitindo consultas e atualizações em O(1). Um array indexado exigiria uma varredura para localizar os itens, o que se torna lento à medida que o carrinho cresce.
P: O que
array_fill_keysfaz? R:array_fill_keys(['a', 'b'], 0)retorna['a' => 0, 'b' => 0]— ele define várias chaves com o mesmo valor em uma única chamada. Nós o usamos no sistema de enquetes para inicializar todas as opções com zero votos.
P: Os dados serão mantidos entre as atualizações da página? R: Não — ao atualizar a página, tudo é apagado. Essa é a natureza “sem estado” do PHP. Na Lição 21, você aprenderá sobre sessões, que permitem que os dados do seu carrinho sejam mantidos entre as solicitações dentro da mesma sessão do usuário.
📖 Resumo
- Carrinho de compras: matrizes associativas + passagem por referência + controle de quantidade
- Lista de tarefas: matrizes multidimensionais +
array_filterpara filtragem + estatísticas - Enquete:
array_fill_keyspara inicialização +arsortpara classificação +array_key_first - Compreender a limitação do modelo “sem estado” leva à necessidade de sessões e bancos de dados
📝 Exercícios
- Adicione pelo menos 5 produtos ao carrinho de compras e inclua uma função
clearCart()que remova tudo. - Adicionar a opção “ordenar por prioridade” (alta → média → baixa) ao sistema de lista de tarefas.
- Adicione uma lógica contra a manipulação de votos à enquete: verifique se a opção existe antes de contabilizar um voto e rejeite as opções inválidas.



