PHP: 实战:数组与函数综合

学了 14 课的语法和函数,是时候把它们串起来了。这三个项目从简单到复杂,让你真正用 PHP 做出可运行的应用。

1. 准备工作

在你之前创建的 htdocs/myphp/ 目录下新建 practice/ 文件夹,所有练习放这里。通过 http://localhost/myphp/practice/ 访问。


2. 项目一:购物车

用数组模拟一个购物车,支持添加商品、修改数量、删除商品、计算总价。

PHP
<?php
// cart.php - 购物车系统

/**
 * 添加商品到购物车
 * @param array  $cart    购物车引用
 * @param string $name    商品名
 * @param float  $price   单价
 * @param int    $qty     数量(默认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];
    }
}

/**
 * 修改商品数量
 */
function updateQty(array &$cart, string $name, int $qty): void {
    if ($qty <= 0) {
        unset($cart[$name]);
    } elseif (isset($cart[$name])) {
        $cart[$name]['qty'] = $qty;
    }
}

/**
 * 删除商品
 */
function removeItem(array &$cart, string $name): void {
    unset($cart[$name]);
}

/**
 * 计算总价
 */
function getTotal(array $cart): float {
    return array_sum(array_map(
        fn($item) => $item['price'] * $item['qty'],
        $cart
    ));
}

// === 测试购物车 ===
$cart = [];

addItem($cart, "PHP教程", 39.90, 2);
addItem($cart, "MySQL入门", 29.90, 1);
addItem($cart, "PHP教程", 39.90, 1);  // 追加1本

echo "<pre>";
echo "购物车内容:\n";
print_r($cart);
echo "\n总价:¥" . getTotal($cart) . "\n";

// 修改数量
updateQty($cart, "MySQL入门", 3);
echo "\n修改后总价:¥" . getTotal($cart) . "\n";

// 删除
removeItem($cart, "PHP教程");
echo "\n删除后:\n";
print_r($cart);
echo "\n最终总价:¥" . getTotal($cart) . "\n";
echo "</pre>";
?>
💡 提示: 这个购物车所有数据存在内存中,刷新页面就会清空。第 21 课学了 Session 之后,购物车就能"记住"你的商品了。


3. 项目二:待办事项列表

用数组管理待办事项:添加、完成、删除、按状态过滤、排序。

▶ 示例:Todo 应用

PHP 📖 仅展示
<?php
// todo.php - 待办事项

/**
 * 添加任务
 */
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"),
    ];
}

/**
 * 标记完成
 */
function markDone(array &$todos, int $id): void {
    foreach ($todos as &$todo) {
        if ($todo['id'] === $id) {
            $todo['done'] = true;
            break;
        }
    }
}

/**
 * 删除任务
 */
function deleteTodo(array &$todos, int $id): void {
    $todos = array_filter($todos, fn($t) => $t['id'] !== $id);
}

/**
 * 获取未完成的任务
 */
function getPending(array $todos): array {
    return array_filter($todos, fn($t) => !$t['done']);
}

/**
 * 统计完成情况
 */
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];
}

// === 测试 Todo ===
$todos = [];
addTodo($todos, "学习 PHP 数组", "high");
addTodo($todos, "练习 foreach 循环", "medium");
addTodo($todos, "写购物车函数", "high");
addTodo($todos, "复习日期函数", "low");

markDone($todos, 1);
markDone($todos, 3);

$stats = getStats($todos);
echo "总计:{$stats['total']},已完成:{$stats['done']},待办:{$stats['pending']}<br>";

echo "<h3>待办事项</h3>";
foreach (getPending($todos) as $todo) {
    $priorityEmoji = [
        'high'   => '🔴',
        'medium' => '🟡',
        'low'    => '🟢',
    ];
    echo $priorityEmoji[$todo['priority']] . " {$todo['title']}<br>";
}
?>
逻辑代码 48 行(超过 40 行限制,仅展示)

4. 项目三:简易投票系统

用关联数组存储选项和票数,支持投票、查看结果、按票数排序。

▶ 示例:投票系统

PHP 📖 仅展示
<?php
// vote.php - 简易投票

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);  // 按票数降序
    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);
}

// === 测试投票 ===
$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>投票结果</h3>";
echo "总票数:" . 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}票 ({$percent}%)<br>";
}

echo "<br>🏆 领先者:" . getWinner($poll) . "<br>";
?>
逻辑代码 42 行(超过 40 行限制,仅展示)

5. 反思:从脚本到应用

这三个项目让你看到:

但你也该注意到了这些限制:

❓ 常见问题

Q 为什么购物车用关联数组而不是索引数组?
A 关联数组用商品名做键,查找和修改 O(1)。索引数组需要遍历查找,商品多了会很慢。
Q array_fill_keys 是什么?
A array_fill_keys(['a','b'], 0) 返回 ['a'=>0, 'b'=>0],一次把多个键设为相同值。投票系统里用它初始化所有选项为 0 票。
Q 这些项目的数据会保存吗?
A 不会,刷新页面全部清空。这是 PHP 的"无状态"特性。第 21 课学习 Session 后,购物车的数据就能在用户会话期间保持。

📖 小节

📝 作业

  1. 为购物车系统添加更多商品(至少 5 种),实现"清空购物车"函数。
  2. 为待办事项系统添加"按优先级排序"功能(high > medium > low)。
  3. 为投票系统添加"防刷票"逻辑:用函数判断该选项是否在投票范围内,无效选项拒绝投票。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏