9.

PHP シングルクォート/ダブルクォート違い完全ガイド (変数展開/エスケープ/ヒアドキュメント)

編集
この記事の要点
  • シングルクォート '…': 変数展開なし。エスケープは \\\' のみ
  • ダブルクォート "…": $var{$obj->prop} を展開。\n / \t / \xNN も解釈
  • ヒアドキュメント <<<EOT: ダブルクォート相当。Nowdoc <<<'EOT': シングル相当
  • 速度差は実用上ほぼ無視可能。可読性SQL Injection 対策で選ぶ
  • JS のテンプレートリテラル `${var}` は PHP のダブルクォート展開に近い

結論: 使い分けの基本

$name = 'Taro';

// シングル: 変数展開しない (リテラル)
echo 'Hello, $name';        // → Hello, $name

// ダブル: 変数展開する
echo "Hello, $name";        // → Hello, Taro
echo "Hello, {$name}さん";   // → Hello, Taroさん

// 改行コード等のエスケープ
echo 'foo\nbar';            // → foo\nbar (リテラル)
echo "foo\nbar";            // → foo[改行]bar

違いを一覧で確認

項目シングル '…'ダブル "…"
変数展開 ($var)
配列展開 ($arr[0])
オブジェクト展開 ($obj->p)
\n \t \r❌ そのまま✅ 改行/タブ等
\xNN \uNNNN
\\ (バックスラッシュ)
\' (クォート)そのまま
\"そのまま

エスケープシーケンス詳細

// シングルクォートで認識される唯一のエスケープ
echo 'I\'m a programmer';          // I'm a programmer
echo 'C:\\Users\\Taro';            // C:\Users\Taro
echo 'foo\nbar';                   // foo\nbar (文字列リテラル)

// ダブルクォートで認識されるエスケープ
echo "line1\nline2";               // 改行
echo "col1\tcol2";                 // タブ
echo "\$price = 100";              // $price = 100 (リテラル)
echo "Hex: \x41";                  // Hex: A (0x41 = 'A')
echo "Unicode: \u{3042}";          // Unicode: あ (PHP 7+)
echo "Octal: \101";                // Octal: A

変数展開の構文

$user = ['name' => 'Taro', 'age' => 30];
$obj = (object)['title' => 'Engineer'];

// シンプル変数 (中括弧不要)
echo "Hello $user";          // 配列を文字列化しようとして Warning

// 配列要素
echo "Name: $user[name]";    // OK (角括弧内はクォート不要)
echo "Name: {$user['name']}"; // ✅ 推奨 (クォート可)

// オブジェクトプロパティ
echo "Job: $obj->title";     // OK
echo "Job: {$obj->title}";   // ✅ 推奨

// メソッド呼び出し (中括弧必須)
echo "Upper: {$obj->getTitle()}";

// 文字列と直結する場合
$word = "test";
echo "$wordABC";             // ❌ $wordABC という変数を探す → 未定義
echo "{$word}ABC";           // ✅ testABC

ヒアドキュメントと Nowdoc

複数行文字列を書くときは ヒアドキュメント (ダブル相当) と Nowdoc (シングル相当) が便利:

$name = 'Taro';

// ヒアドキュメント (変数展開あり)
$html = <<<EOT
<div>
    Hello, $name さん!
    今日は {$today} です。
</div>
EOT;

// Nowdoc (変数展開なし、識別子をクォート)
$sql = <<<'SQL'
SELECT *
FROM users
WHERE name = '$name'   -- リテラルの $name 文字列
SQL;

// PHP 7.3+ 終了識別子のインデント可
function template(): string {
    return <<<EOT
        Hello
        World
        EOT;  // ← この空白分が削除される
}

性能差はあるか?

「シングルクォートの方が速い」とよく言われますが、現代の PHP (7+) では 差はほぼ無視できるレベルです。可読性とエスケープミス防止で選んでください。

// マイクロベンチマーク (PHP 8.3, 1000 万回)
// 'plain string'    : 0.31s
// "plain string"    : 0.32s   (差はほぼなし)
// "with $var"       : 0.45s   (展開コストあり)
// 'pre' . $var      : 0.42s   (連結)
// "pre {$var}"      : 0.46s   (中括弧展開)

// 結論: マイクロ最適化は不要。可読性優先で OK

SQL Injection とクォート

クォートの違いを理解していないと SQL Injection を作り込みます:

// ❌ 危険: ダブルクォートで変数展開
$id = $_GET['id'];  // "1 OR 1=1"
$sql = "SELECT * FROM users WHERE id = $id";
// → SELECT * FROM users WHERE id = 1 OR 1=1

// ✅ プリペアドステートメント (PDO)
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);

// ✅ Eloquent (Laravel)
User::where('id', $id)->first();

JavaScript との比較

言語シングルダブル変数展開
PHPリテラル変数展開ありダブル / ヒアドキュメント
JavaScript区別なし区別なしテンプレートリテラル `${var}`
Python区別なし区別なしf-string f"{var}"
Rubyリテラル寄り変数展開ありダブル "#{var}"

FAQ

Q: チーム規約でどちらを推奨すべき?
A: PSR-12 では明示的な規定はありませんが、Symfony / Laravel コードは 変数展開が必要なときだけダブルを使う傾向。基本シングルを推奨します。

Q: ダブルクォート内の $ をリテラルにしたい
A: \$ でエスケープ。例: "\$price = $price"

Q: HTML 属性が多くてダブルクォート地獄
A: シングルの中にダブルが書けるので '<a href="...">' が楽。または sprintf やヒアドキュメントを使う。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストール方法
  2. 文法
  3. Composerのインストール
  4. 内部関数
  5. フレームワーク
  6. エラー一覧
  7. 改行出力
  8. printとechoの違い
  9. シングルクォートとダブルクォートの違い
  10. returnとyieldの違い
  11. var_dumpをログ出力
  12. CSV読み込み
  13. 待機・処理の遅延
  14. ログファイルにエラーを出力する方法
  15. エラーログ出力関数
  16. URLパラメータの配列化
  17. empty, is_null. issetの判定比較表
  18. httpステータスコードの付与
  19. バージョンの確認
  20. php.ini
  21. APIを呼び出す方法
  22. 外部ファイルを呼び出す方法
  23. カンマ区切りの文字列を配列に変換
  24. 配列からランダムに値を取り出す方法
  25. Webスクレイピング

最近更新/作成されたページ