You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQLi多表查询与单条宠物数据重复更新问题求助

问题分析

你的问题根源很清晰:更新操作的逻辑被放在了遍历所有宠物的while循环内部。当你点击提交按钮后,页面重新加载时会先查询当前用户的所有宠物,然后每循环一只宠物就会检查一次$_GET参数。只要满足条件(比如buy=clean、资金足够),就会执行一次更新——你有多少只宠物,就会执行多少次更新,这就是指定宠物信息被重复修改的原因。

解决方案

我们需要把更新逻辑和宠物展示逻辑彻底分开:先处理提交的更新请求(只执行一次),再查询并展示所有宠物信息。这样不管用户有多少只宠物,更新操作只会触发一次。

具体调整思路:

  1. 先获取用户当前资金,用于后续的更新条件判断;
  2. 检查是否存在$_GET['buy']和$_GET['identifier']参数,若存在则执行对应的更新操作(完全脱离宠物遍历循环);
  3. 最后再查询所有宠物信息,循环展示每只宠物的内容和操作按钮。
修改后的完整代码
<?php
// 先获取用户当前资金,用于后续条件判断
$statement = $mysqli->prepare("SELECT money FROM users WHERE fbid = ?");
$statement->bind_param("s", $_SESSION['FBID']);
$statement->execute();
$statement->bind_result($money);
$statement->fetch(); // 仅查询一行数据,无需while循环
$statement->close();

// 处理更新请求:放在宠物遍历循环外,确保只执行一次
if (isset($_GET['buy']) && isset($_GET['identifier'])) {
    $buyType = $_GET['buy'];
    $targetPet = $_GET['identifier'];

    if ($buyType === 'clean' && $money >= 5) {
        // 先检查目标宠物的当前清洁度是否符合更新条件
        $checkStmt = $mysqli->prepare("SELECT clean FROM pets WHERE fbid = ? AND petname = ?");
        $checkStmt->bind_param("ss", $_SESSION['FBID'], $targetPet);
        $checkStmt->execute();
        $checkStmt->bind_result($currentClean);
        $checkStmt->fetch();
        $checkStmt->close();

        if ($currentClean <= 95) {
            // 更新宠物清洁度
            $updatePetStmt = $mysqli->prepare("UPDATE pets SET `clean` = `clean` + 5 WHERE fbid = ? AND petname = ?");
            $updatePetStmt->bind_param("ss", $_SESSION['FBID'], $targetPet);
            $updatePetStmt->execute();
            $updatePetStmt->close();

            // 扣除用户资金
            $updateUserStmt = $mysqli->prepare("UPDATE users SET `money` = `money` - 5 WHERE fbid = ?");
            $updateUserStmt->bind_param("s", $_SESSION['FBID']);
            $updateUserStmt->execute();
            $updateUserStmt->close();

            header("Location: /pets.php?success=clean");
            exit; // 跳转后终止脚本,避免后续代码执行
        }
    } elseif ($buyType === 'health' && $money >= 7) {
        // 先检查目标宠物的当前健康度是否符合更新条件
        $checkStmt = $mysqli->prepare("SELECT health FROM pets WHERE fbid = ? AND petname = ?");
        $checkStmt->bind_param("ss", $_SESSION['FBID'], $targetPet);
        $checkStmt->execute();
        $checkStmt->bind_result($currentHealth);
        $checkStmt->fetch();
        $checkStmt->close();

        if ($currentHealth <= 90) {
            // 更新宠物健康度
            $updatePetStmt = $mysqli->prepare("UPDATE pets SET `health` = `health` + 10 WHERE fbid = ? AND petname = ?");
            $updatePetStmt->bind_param("ss", $_SESSION['FBID'], $targetPet);
            $updatePetStmt->execute();
            $updatePetStmt->close();

            // 扣除用户资金
            $updateUserStmt = $mysqli->prepare("UPDATE users SET `money` = `money` - 7 WHERE fbid = ?");
            $updateUserStmt->bind_param("s", $_SESSION['FBID']);
            $updateUserStmt->execute();
            $updateUserStmt->close();

            header("Location: /pets.php?success=health");
            exit;
        }
    }
}

// 最后查询并展示所有宠物信息
if ($stmt = $mysqli->prepare("SELECT clean,health,petname FROM pets WHERE fbid = ?")) {
    $stmt->bind_param('s', $_SESSION['FBID']);
    $stmt->execute();
    $stmt->store_result();
    $num_of_rows = $stmt->num_rows;
    $stmt->bind_result($clean,$health,$petname);

    while ($stmt->fetch()) {
        echo "{$petname} welcomes you!<br>";

        // 展示健康护理按钮(判断条件)
        if ($health <= 90 && $money >= 7) {
            echo "<form method='GET'>
                    <input type='hidden' name='identifier' value='{$petname}'>
                    <input type='hidden' name='buy' value='health'>
                    <input type='submit' value='Healthcare (G$7)'>
                  </form>";
        }

        // 展示清洁按钮(判断条件)
        if ($clean <= 95 && $money >= 5) {
            echo "<form method='GET'>
                    <input type='hidden' name='identifier' value='{$petname}'>
                    <input type='hidden' name='buy' value='clean'>
                    <input type='submit' value='Clean (G$5)'>
                  </form>";
        }
    }

    $stmt->free_result();
    $stmt->close();
}
?>
关键优化点
  • 更新逻辑独立:将更新操作从宠物遍历循环中抽离,确保提交请求后只执行一次更新;
  • 前置属性检查:在更新前先查询目标宠物的当前属性值,避免出现清洁度/健康度超过100的不合理情况;
  • 跳转后终止脚本:使用exit确保跳转后脚本不再继续执行,避免不必要的代码运行;
  • 简化资金查询:因为users表仅查询一行数据,直接用一次fetch()即可,无需多余的while循环。

内容的提问来源于stack exchange,提问作者krisz44g

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:47:35