| この記事の要点 |
|
結論: 使い分けの基本
$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 やヒアドキュメントを使う。
子ページ
子ページはありません
同階層のページ
- インストール方法
- 文法
- Composerのインストール
- 内部関数
- フレームワーク
- エラー一覧
- 改行出力
- printとechoの違い
- シングルクォートとダブルクォートの違い
- returnとyieldの違い
- var_dumpをログ出力
- CSV読み込み
- 待機・処理の遅延
- ログファイルにエラーを出力する方法
- エラーログ出力関数
- URLパラメータの配列化
- empty, is_null. issetの判定比較表
- httpステータスコードの付与
- バージョンの確認
- php.ini
- APIを呼び出す方法
- 外部ファイルを呼び出す方法
- カンマ区切りの文字列を配列に変換
- 配列からランダムに値を取り出す方法
- Webスクレイピング
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38