6

現時点では、楽しみのためにいくつかのウェブサイトを作成していますが、ある時点で立ち往生しています。

グループクエストを実行したいのですが、グループのメンバーなら誰でも開始できます。グループの全員が同じ量のゴールド、経験値を取得し、同じクールダウンを共有します。データベースに 3 つのテーブルがあります (重要な情報のみを表示します)

Members:
username, level, experience, playergold

Levels:
level, required_experience

Groups:
leader, member_1, member_2, member_3, last_quest_started, quest_cooldown

Quests:
success_message, failed_message, chance, minimum_experience, maximum_experience, minimum_gold, maximum_gold, cooldown

グループで last_quest_started と quest_cooldown を更新し、各メンバーのレベル、経験値、playergold を更新したい

そのため、グループ メンバーの各ユーザー名を取得した後、クエスト データ、経験値とゴールドを計算します。これを使用して更新します:

if($select_members_info_stmt = $mysqli->prepare("SELECT members.username, members.level, members.experience, members.playergold, levels.required_experience FROM members INNER JOIN levels ON members.level = levels.level WHERE ((members.username = ?) OR (members.username = ?) OR (members.username = ?) OR(members.username = ?))"))
{
    $select_members_info_stmt->bind_param('ssss', $leader, $member_1, $member_2, $member_3);
    $select_members_info_stmt->execute();
    $select_members_info_stmt->bind_result($selected_username, $level, $experience, $playergold, $required_experience);
    while($select_members_info_stmt->fetch())
    {
        $now = time();

        if($update_user_stats_stmt = $mysqli->prepare("UPDATE members SET level = ?, experience = ?, playergold = ? WHERE username = ?"))
        {
            $update_user_stats_stmt->bind_param('iiiiis', $new_level, $new_experience, $new_gold, $now, $cooldown, $selected_username);
            $update_user_stats_stmt->execute();
            if($update_user_stats_stmt->affected_rows == 0)
            {
                    echo '<div>Because of a system error it is impossible to perform a task, we apologize for this inconvience. Try again later.</div>';
            }
            $update_user_stats_stmt->close();
        }
        else                                
        {
            printf("Update user stats error: %s<br />", $mysqli->error);
        }
    }
    $select_members_info_stmt->close();
    echo '<div>'.$success_message.'</div><br />';
}
else
{
    printf("Select members info error: %s<br />", $mysqli_error);
}

しかし、私は取得し続けます:

ユーザー統計の更新エラー: コマンドが同期していません。現在、このコマンドを実行することはできません (グループがいっぱいになったときのサイズである 4 回)。

$select_members_info_stmt を閉じることができないため、非同期エラーを回避する解決策が見つかりません。フェッチが停止するためです。

本当にどうすればいいのか分からないので教えてください。

4

2 に答える 2

6

そのようにネストすることはできませんexecute()

最善の解決策は、そのメンバーのリストをarray()一度に投げ、接続を閉じ、その配列を繰り返して各レコードを更新することです。

次のようになります。

$select_members_info_stmt->bind_param('ssss', $leader, $member_1, $member_2, $member_3);
$select_members_info_stmt->execute();
$select_members_info_stmt->bind_result($selected_username, $level, $experience, $playergold, $required_experience);

$members = array();
while($select_members_info_stmt->fetch())
{
    // tossing into the array
    $members[] = array(
        'selected_username' =>$selected_username, 
        'level' => $level, 
        'experience' => $experience, 
        'playergold' => $playergold, 
        'required_experience' => $required_experience
    );
}
$select_members_info_stmt->close();

// Now iterate through the array and update the user stats
foreach ($members as $m) {
    if($update_user_stats_stmt = $mysqli->prepare("UPDATE members SET level = ?, experience = ?, playergold = ? WHERE username = ?"))
    {
        // Note that you need to use $m['selected_username'] here. 
        $update_user_stats_stmt->bind_param('iiiiis', $new_level, $new_experience, $new_gold, $now, $cooldown, $m['selected_username']);
        $update_user_stats_stmt->execute();
        if($update_user_stats_stmt->affected_rows == 0)
        {
                echo '<div>Because of a system error it is impossible to perform a task, we apologize for this inconvience. Try again later.</div>';
        }
        $update_user_stats_stmt->close();
    }
    else                                
    {
        printf("Update user stats error: %s<br />", $mysqli->error);
    }

}
于 2013-01-23T00:14:39.020 に答える
3

mysql への同じ接続でアクティブに実行中の準備済みステートメントをネストすることはできません。ステートメントを呼び出すとexecute()、その準備済みステートメントが閉じられるまで、同じ接続で別のステートメントを実行することはできません。最初のプリペアド ステートメントでのフェッチは、2 番目のステートメントで実行を開始すると失敗します。

接続ごとに 1 つの「ライブ」ステートメントのみを準備し、mysql サーバーで実行できます

準備されたステートメントをネストする必要がある場合は、2 つの別個の mysqli 接続を確立できます。

于 2013-01-22T23:52:50.497 に答える