この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: エスケープ文字
SEOタイトル: PHP エスケープ文字 (シングル/ダブルクォート) 完全ガイド

この記事の要点
  • ダブルクォートでは \n / \r / \t / \\ / \$ / \" / \xNN / \u{NNNN} (PHP 7+) が使える
  • シングルクォート\\\' の 2 つだけ。\nそのまま文字列リテラルになる
  • HTML 出力時は htmlspecialchars($str, ENT_QUOTES, "UTF-8") で XSS 対策
  • SQL は addslashes連結禁止PDO::prepare + Prepared Statement で SQL Injection 防御
  • PHP コードを文字列に埋めるなら / ?><?php 化、または heredoc/nowdoc を使う

ダブルクォート vs シングルクォートの違い

エスケープシングル '...'ダブル "..."意味
\nそのまま \n改行 (LF)Line Feed (0x0A)
\rそのまま \rキャリッジリターンCR (0x0D)
\tそのまま \t水平タブ0x09
\vそのまま垂直タブ0x0B
\fそのまま改ページ0x0C
\0そのままヌル文字0x00
\\バックスラッシュバックスラッシュ両方OK
\'シングルクォートそのまま \'-
\"そのまま \"ダブルクォート-
\$そのまま \$$ 記号(変数展開抑止)-
\xNNそのまま16進文字 (例 \x41 → A)-
\NNNそのまま8進文字-
\u{NNNN}そのままUnicode (PHP 7+)例 \u{1F600} → 😀

具体例

// シングルクォート: \n はそのまま文字
echo 'Hello\nWorld';
// → Hello\nWorld (改行されない)

// ダブルクォート: \n は改行
echo "Hello\nWorld";
// → Hello
//   World

// 変数展開
$name = 'Taro';
echo 'Hello, $name';       // Hello, $name (展開されない)
echo "Hello, $name";       // Hello, Taro
echo "Hello, \$name";      // Hello, $name (\$ でエスケープ)

// 配列・オブジェクト展開
$arr = ['name' => 'Taro'];
echo "Hello, {$arr['name']}";   // Hello, Taro
echo "Hello, $arr[name]";       // Hello, Taro (簡易記法、キーはクォートなし)

// Unicode (PHP 7+)
echo "\u{1F600}";   // 😀
echo "\u{3042}";    // あ

// 16進文字
echo "\x41\x42\x43";   // ABC

heredoc と nowdoc

複数行の文字列リテラルは heredoc / nowdoc がベター:

$name = 'Taro';

// heredoc - ダブルクォートと同じ動作(変数展開あり)
$html = <<
  Hello, $name
HTML; // nowdoc - シングルクォートと同じ動作(変数展開なし) $raw = <<<'TEXT' Path: C:\Users\$name \nは改行しません TEXT; // インデント付き heredoc (PHP 7.3+) function getHtml(): string { return <<

$name

HTML; // 終端タグのインデント分が全行から削除される }

HTML エスケープ (XSS 対策)

ユーザー入力をそのまま HTML に出すと XSS。必ず htmlspecialchars():

// ❌ XSS 脆弱
echo "

Hello, $name

"; // $name = "" だと実行される // ✅ htmlspecialchars で対策 echo "

Hello, " . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . "

"; // 第2引数のフラグ // ENT_QUOTES - シングル+ダブル両方をエスケープ(推奨) // ENT_HTML5 - HTML5 仕様(XHTML は ENT_XHTML) // ENT_SUBSTITUTE - 不正バイト列を U+FFFD に置換 // ENT_DISALLOWED - 文書型で許可されない文字を置換 // 推奨フォーム function h($s): string { return htmlspecialchars($s ?? '', ENT_QUOTES | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8'); } echo "

" . h($name) . "

"; // htmlentities - htmlspecialchars + 全文字エンティティ化(重い、通常不要) echo htmlentities('é', ENT_QUOTES, 'UTF-8'); // é
文字エスケープ後
&&
<<
>>
""
'' (ENT_QUOTES)

SQL Injection 対策 (PDO Prepared Statement)

絶対に文字列連結で SQL を組まないのが鉄則:

// ❌ SQL Injection 脆弱
$id = $_GET['id'];   // "1 OR 1=1"
$pdo->query("SELECT * FROM users WHERE id = $id");

// ❌ addslashes だけでは不十分(マルチバイト攻撃に弱い)
$id = addslashes($_GET['id']);
$pdo->query("SELECT * FROM users WHERE id = '$id'");

// ✅ Prepared Statement で安全
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$_GET['id']]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);

// ✅ 名前付きバインド
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute([':email' => $email]);

// LIKE 句のワイルドカードエスケープ
$keyword = str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $keyword);
$stmt = $pdo->prepare("SELECT * FROM logs WHERE msg LIKE ? ESCAPE '\\\\'");
$stmt->execute(["%{$keyword}%"]);

JSON / URL エスケープ

// JSON
$arr = ['name' => 'Taro', 'msg' => 'Hello "World"'];
echo json_encode($arr);                  // {"name":"Taro","msg":"Hello \"World\""}
echo json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

// URL
$keyword = 'php 入門';
$url = 'https://example.com/search?q=' . urlencode($keyword);
// → ?q=php+%E5%85%A5%E9%96%80

// rawurlencode - スペースを + ではなく %20 に
$path = 'docs/' . rawurlencode($filename);

// パラメータ全部
$params = ['q' => $keyword, 'page' => 2];
$url = 'https://example.com/search?' . http_build_query($params);

非推奨: addslashes / stripslashes / Magic Quotes

古い記事で出てくる addslashes 系はもう使わないでください:

// ❌ 非推奨(古い解説に出てくる)
$safe = addslashes($input);    // ' " \ \0 にバックスラッシュ追加
$orig = stripslashes($safe);

// ❌ Magic Quotes は PHP 5.4 で廃止
get_magic_quotes_gpc();   // 常に false (PHP 5.4+)、PHP 8 で関数自体削除

// ✅ 現代の対策
// SQL    → PDO Prepared Statement
// HTML   → htmlspecialchars
// JSON   → json_encode
// シェル → escapeshellarg / escapeshellcmd

PHP コードを文字列に埋めたいとき

// nowdoc が最強(変数展開もエスケープも不要)
$snippet = <<<'PHP'
' . htmlspecialchars($snippet, ENT_QUOTES, 'UTF-8') . '
';

FAQ

Q: シングルとダブル、どちらを使うべき?
A: 変数展開・エスケープシーケンスが要らないならシングル(わずかに高速)。展開したいときだけダブル。

Q: 全角スペースもエスケープ必要?
A: 不要。HTML エスケープ対象は & / < / > / " / ' のみ。

Q: str_replace で自前エスケープを書くのは?
A: 危険。順序・抜けが起きやすい。必ず標準関数 htmlspecialchars / json_encode / PDO::prepare を使ってください。