リクエスト詳細
🐛 バグ報告
対応完了
対象アプリ: 野球スコアブック BallGraph
アンドゥ時のIDチェックにより正当な取り消しが常に失敗する
## 1. 不具合の内容
`pages/score.php` の `undo_at_bat` アクション処理で、DELETE クエリが「最新レコードのIDが `$undo_at_bat_id` と一致する場合のみ削除」という条件になっているにもかかわらず、クライアント側から渡される `undo_at_bat_id` が古くなる(=最新IDと食い違う)ケースが頻繁に発生し、取り消しが実行されない。
## 2. 根拠・発生しそうな条件
該当コード:
```sql
DELETE ab FROM at_bats ab
INNER JOIN (
SELECT id FROM at_bats WHERE game_id = ? ORDER BY id DESC LIMIT 1
) latest ON latest.id = ab.id
INNER JOIN games g ON g.id = ab.game_id AND g.session_token = ?
WHERE ab.id = ? AND ab.game_id = ?
```
このクエリは `latest.id = ab.id` かつ `ab.id = ?`(= `$undo_at_bat_id`)の両方が真のときのみ削除する。つまり「DBの現在の最新IDがクライアントから送られた `undo_at_bat_id` と同じ」でないと削除されない。
- スコア画面は JavaScript で動作しており、打席入力のたびに非同期 POST → 画面再描画という流れが想定される。クライアントが保持する「最後に登録したat_bat ID」と、実際のDBの最新IDがずれる状況(同一セッションで別タブ操作、ページ再読み込み後のundo試行、連続undo操作など)で `rowCount() === 0` となり、取り消しが無音で失敗する。
- さらに `$_SESSION['flash']` による成功メッセージも表示されないため、ユーザーは取り消しが失敗したことに気づけない。
## 3. 期待動作
「取り消し」ボタンを押したとき、そのゲームの **最新の打席結果1件** が削除される。セッション所有チェック(`session_token` の照合)は維持する。
## 4. 修正方針
`undo_at_bat_id` による照合を廃止し、「game_id と session_token が一致するゲームの at_bats を最新1件削除」するシンプルなクエリに変更する。
```php
if ($action === 'undo_at_bat') {
// session_token で所有確認済みの $id を使い、最新1件をそのまま削除
$delete = app_db()->prepare(
"DELETE FROM at_bats
WHERE game_id = ?
ORDER BY id DESC
LIMIT 1"
);
$delete->execute([$id]);
// $id はページ先頭で session_token 照合済みのため追加チェック不要
if ($delete->rowCount() > 0) {
$_SESSION['flash'] = '直前の打席結果を取り消しました。';
} else {
$_SESSION['flash'] = '取り消せる打席結果がありません。';
}
}
```
クライアント側 JavaScript からは `undo_at_bat_id` の送信が不要になるため、該当 hidden input / fetch パラメータも削除する。undo スタック管理(最大20ステップ)はクライアント側の JS で引き続き行い、redo 用ペイロードの保持方法は現行のまま変更しない。
`pages/score.php` の `undo_at_bat` アクション処理で、DELETE クエリが「最新レコードのIDが `$undo_at_bat_id` と一致する場合のみ削除」という条件になっているにもかかわらず、クライアント側から渡される `undo_at_bat_id` が古くなる(=最新IDと食い違う)ケースが頻繁に発生し、取り消しが実行されない。
## 2. 根拠・発生しそうな条件
該当コード:
```sql
DELETE ab FROM at_bats ab
INNER JOIN (
SELECT id FROM at_bats WHERE game_id = ? ORDER BY id DESC LIMIT 1
) latest ON latest.id = ab.id
INNER JOIN games g ON g.id = ab.game_id AND g.session_token = ?
WHERE ab.id = ? AND ab.game_id = ?
```
このクエリは `latest.id = ab.id` かつ `ab.id = ?`(= `$undo_at_bat_id`)の両方が真のときのみ削除する。つまり「DBの現在の最新IDがクライアントから送られた `undo_at_bat_id` と同じ」でないと削除されない。
- スコア画面は JavaScript で動作しており、打席入力のたびに非同期 POST → 画面再描画という流れが想定される。クライアントが保持する「最後に登録したat_bat ID」と、実際のDBの最新IDがずれる状況(同一セッションで別タブ操作、ページ再読み込み後のundo試行、連続undo操作など)で `rowCount() === 0` となり、取り消しが無音で失敗する。
- さらに `$_SESSION['flash']` による成功メッセージも表示されないため、ユーザーは取り消しが失敗したことに気づけない。
## 3. 期待動作
「取り消し」ボタンを押したとき、そのゲームの **最新の打席結果1件** が削除される。セッション所有チェック(`session_token` の照合)は維持する。
## 4. 修正方針
`undo_at_bat_id` による照合を廃止し、「game_id と session_token が一致するゲームの at_bats を最新1件削除」するシンプルなクエリに変更する。
```php
if ($action === 'undo_at_bat') {
// session_token で所有確認済みの $id を使い、最新1件をそのまま削除
$delete = app_db()->prepare(
"DELETE FROM at_bats
WHERE game_id = ?
ORDER BY id DESC
LIMIT 1"
);
$delete->execute([$id]);
// $id はページ先頭で session_token 照合済みのため追加チェック不要
if ($delete->rowCount() > 0) {
$_SESSION['flash'] = '直前の打席結果を取り消しました。';
} else {
$_SESSION['flash'] = '取り消せる打席結果がありません。';
}
}
```
クライアント側 JavaScript からは `undo_at_bat_id` の送信が不要になるため、該当 hidden input / fetch パラメータも削除する。undo スタック管理(最大20ステップ)はクライアント側の JS で引き続き行い、redo 用ペイロードの保持方法は現行のまま変更しない。
💬 返信 (3)
🛠 開発を開始しました (バグ修正 ballgraph)
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
📝 開発が完了しました
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
✅ リリース完了のお知らせ
ご要望いただいた「野球スコアブック BallGraph」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=ballgraph
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/ballgraph/
ご利用ありがとうございます!
ご要望いただいた「野球スコアブック BallGraph」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=ballgraph
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/ballgraph/
ご利用ありがとうございます!
Echo
Iris