レガシーPHPリファクタ 5:手動CSVエスケープと `stripslashes()` を廃止して `fputcsv()` に移行する

レガシーPHPリファクタ 5:手動CSVエスケープと `stripslashes()` を廃止して `fputcsv()` に移行する
Smarty動的Webサイト構築入門サンプルソース. Contribute to ninton/smartybook development by creating an account on GitHub.

PHPのレガシーコードを読み解いていると、思わず「時代を感じる…」と頷いてしまう実装に出会うことがあります。

今回は、手動でダブルクォーテーションのエスケープや包囲を行っていた独自関数 convertNl() を全廃し、現代的な fputcsv() による実装へとリファクタリングした事例をまとめました。


修正前後のコード比較

修正前(独自関数+手動フォーマット生成)

function convertNl(string $str): string
{
    $str = stripslashes($str);
    $str = str_replace('"', '""', $str);
    return '"' . $str . '"';
}

// 書き込むデータを生成
$title    = convertNl($rawTitle);
$contents = convertNl($rawContents);
$string   = "$id,$category,$title,$contents,$date,$image\n";

$isSuccess = (fwrite($fp, $string) !== false);

修正後(fputcsv() への一本化)

// 書き込む配列データを準備(fputcsv が適切にエスケープとクォートを処理)
$row = [$id, $category, $title, $contents, (string)$date, $image];

// CSVファイルに書き込み (PHP 8.4+ escape: '' 明示)
$isSuccess = (fputcsv($fp, $row, escape: '') !== false);


主な変更点と改善の理由

1. 独自エスケープ処理(convertNl)の全廃

修正前は、ダブルクォーテーションの重ね合わせ("")や前後のクォート囲みを自作関数で行い、文字列連結でCSVの1行を生成していました。

こうした自作ロジックは、改行コードの扱い漏れや特殊文字の処理ミスによるフォーマット崩れを引き起こしがちです。修正後では、CSVフォーマット仕様(RFC 4180)に準拠した標準関数 fputcsv() にすべて委ねることで、安全かつ確実な書き込みを実現しています。

2. PHP 8.4 以降を見据えた escape: '' の明示

PHP 8.4 では、fputcsv() のデフォルトのエスケープ文字仕様(\)に関する非推奨警告が出力されるよう変更が進んでいます。標準的なCSV仕様に合わせるため、名前付き引数を用いて escape: '' を明示的に指定しています。


コラム:懐かしの magic_quotes_gpc と stripslashes()

コードの中に残っていた stripslashes($str) は、かつての magic_quotes_gpc 対策の名残(遺物) です。

当時は $_POST や $_GET などの入力値に対し、PHPの設定(magic_quotes_gpc = On)によって自動で addslashes() が適用され、クォートが \' や \" のようにエスケープされる仕組みが存在していました。そのため、「余計なお世話で付与されたバックスラッシュを stripslashes() で元に戻す」という奇妙な定型処理が広く行われていました。

現代における問題点

  1. magic_quotes_gpc は完全に削除済み PHP 5.3 で非推奨となり、PHP 5.4 で完全に削除されました。現在の PHP 環境では自動エスケープ自体が発生しません。
  2. データの破損(バグ)につながる 自動エスケープが行われない現代の環境で無条件に stripslashes() を実行すると、ユーザーが意図して入力したバックスラッシュ(パス表記や正規表現など)が勝手に消去され、データが破壊されてしまいます。

まとめ

  • stripslashes() は即刻削除: 現代のPHPでは不要なだけでなく、データを破損させるリスクがあります。
  • CSV生成は fputcsv() に任せる: 改行・カンマ・クォートのエスケープを安全に自動処理してくれる標準関数を使いましょう。

過去の互換性対策として残ったコードを整理し、標準関数へ寄せていくことで、コードの可読性と堅牢性を大幅に向上させることができます。

参考PR

refactor(chapter2): CSV保存処理の fputcsv 化・自作エスケープ関数廃止と入力バリデーションの追加 by ninton · Pull Request #714 · ninton/smartybook
概要02_06.php(登録完了・CSV保存処理)において、歴史的経緯の残る自作エスケープ関数(convertNl)を廃止して標準の fputcsv() へ移行し、さらに 02_05.php と同等の入力バリデーション(400 Bad Re...
タイトルとURLをコピーしました