動くけれど危ないコードを、先に直す順番にした
エラーで止まるコードより、止まらずに動いてしまうSQLの連結のほうが優先度は上でした。

この記事の結論
- エラーで止まるものは、放置しても被害が出ない
- 止まらずに動くもののほうが危ない
- 置き換えは機械的だが、確認は1件ずつ要る
- エラーで止まるものは、放置しても被害が出ない
- 止まらずに動くもののほうが危ない
- 置き換えは機械的だが、確認は1件ずつ要る
移行の順番を「落ちるものから直す」にしていたが、途中で変えた。理由を書く。
落ちるコードは、実は安全
mysql_connectは新しいPHPで即座に落ちる。落ちるということは、本番に出せないということだ。気づかずに公開される心配がない。
対してSQLの文字列連結は、PHP 8でもそのまま動く。エラーも警告も出ない。
$sql = "SELECT * FROM items WHERE id = " . $_GET['id'];これは移行が「成功」したあとも、そのまま残る。動いているので誰も気づかない。
だから順番を変えた
- 動くけれど危ないもの(SQLの連結、エスケープ漏れ)
- 落ちるもの(消えた関数)
- 動くし危なくないもの(var、PHP4形式のコンストラクタ)
2番は作業すれば必ず気づくので、放っておいても取りこぼさない。取りこぼすのは1番だけなので、先にやる。
置き換えの形は決まっている
連結をやめて、値を分けて渡す形にする。
$stmt = $pdo->prepare('SELECT * FROM items WHERE id = :id');
$stmt->execute(['id' => $id]);
$row = $stmt->fetch();形が決まっているので、AIに任せやすい部分だ。何十箇所あっても、やることは同じ。
ただし確認は1件ずつ要る
任せられるのは書き換えまでで、確認は別だ。引っかかったのは次のような箇所だった。
- テーブル名やカラム名を変数で差し込んでいる(プレースホルダにできない)
- IN句に配列を展開している(個数だけプレースホルダを作る必要がある)
- ORDER BY の方向を変数で渡している
値ではない部分は、プレースホルダにできない。ここは許可する値を列挙して突き合わせるしかなく、機械的な置き換えでは済まない。
公式の記述
「動くけれど危ない」の筆頭が、文字列と数値の比較だ。PHP 8.0 で == の判定が変わった。
0 == "foo"… PHP 7 は true / PHP 8 は false0 == ""… PHP 7 は true / PHP 8 は false42 == "42foo"… PHP 7 は true / PHP 8 は false
エラーは出ない。条件分岐の結果だけが静かに変わる。落ちるコードより、こちらを先に探すほうが被害が小さい。
出典: PHP Manual「Backward Incompatible Changes(PHP 8.0)」(2026年10月12日確認)
AIはここを黙って通す
テーブル名の差し込みを含むコードを渡したら、プレースホルダを使った形に書き換えて、問題なさそうに見える結果を返してきた。実際には動かない。
「プレースホルダにできない箇所があれば、書き換えずに指摘して」と先に言っておくと、分けて返ってくるようになった。できないことを言わせる指示を、最初に入れておく。
一括置換はしない
同じ形なので一括置換したくなるが、やめた。
連結している変数が、その行より上で何を通ってきているかは行ごとに違う。すでにintval()を通してある箇所もあれば、$_GETから直の箇所もある。見た目が同じでも、安全度が違う。
直した数を数える
走査スクリプトを回し直すと、残件が減る。これを作業のたびに記録した。
SQLの文字列連結 42箇所 → 31 → 18 → 0進捗が数字で出ると、終わりが見える。見えないまま進めると、途中で雑になる。
エスケープも同じ考え方
画面に出す側も、動くけれど危ない側だ。echo $row['name'];は動く。
連結と同じく、走査で数えて、順番にhtmlspecialchars()を通す。出力の数は入力の数より多いことが多く、こちらのほうが件数は増えた。
移行前にやるか、後にやるか
迷ったが、移行前にやった。移行後だと、新しいフレームワークの書き方に変わっていて、どこが元のコードだったか分からなくなるからだ。
古い形のまま安全にしてから移すほうが、1つずつの変更が小さくなり、問題が起きたとき原因を絞りやすかった。
あわせて読む
- 入力欄の検査を頼むとき、画面側だけでは足りないと知った — ブラウザ側で止めても、裏から送られると通ります。両方要ると分かった話です。
- サイトが遅い原因を、推測ではなく測って特定した — 重そうな箇所を勘で直していました。測ってから直すと、全然違う場所が原因でした。
- サイトの控えを取る手順を、1つのファイルにまとめた — 手順を覚えておけず、取らない日が出ていました。実行できる形にした話です。
まとめ
移行作業で見落とすのは、エラーにならない箇所だ。落ちるものは必ず気づくので、後回しでよい。
動くけれど危ないものを先に数え、先に直す。この順番にしてから、移行後に「動いているけれど直っていない」が残らなくなった。
新しい記事が出たら、ブラウザの通知でお知らせします。
メールアドレスの登録は要りません。いつでも止められます。
関連記事
RELATED
テストが1つも無いコードに、どこからテストを足すか
全部にテストを書くのは無理です。移行で触る所だけに絞ったら、現実的な分量になりました。
HTTPの仕組みを図にした。前の話を覚えていない、という前提
HTTPは1往復で完結し、前のやり取りを覚えていません。ログイン状態が保てる理由と、ステータスコードの読み方を図で整理し…
Laravelへ移すとき、どこから手を付けるか決めた
全部を一度に移すと戻れなくなります。順番を決めたら、途中で止めても使える状態を保てました。