タイトル: シングルクォートとダブルクォートの違い
SEOタイトル: 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 = <<
Hello, $name さん!
今日は {$today} です。
性能差はあるか?
「シングルクォートの方が速い」とよく言われますが、現代の 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: シングルの中にダブルが書けるので '' が楽。または sprintf やヒアドキュメントを使う。