PHPの「’」と「”」に違いはあるのか?どんな場面で使ったら良いか調べてみた。
こんにちは、Cメロです。
今日はPHPで使用する「’」(シングルクォーテーション)と「”」(ダブルクォーテーション)の違いを調べてみました。
公式ドキュメントはこちら。文字列についてのページに記載がありました。公式ドキュメントでは「’」を「引用符」、「”」を「二重引用符」と表記しています。
調べた結果、大きな違いとしては以下が挙げられるかなと思います。
- エスケープシーケンスの種類
- 変数のパースが発生するかしないか
順番に確認していきます。
エスケープシーケンスの種類
まずは一つ目の違いはエスケープシーケンスの種類です。
公式ドキュメントの文字列のページを確認すると以下のような記載があります。
引用符
引用符
文字列を指定する最も簡単な方法は、引用符 (文字
'
) で括ることです。引用符をリテラルとして指定するには、バックスラッシュ (
\
) でエスケープする必要があります。 バックスラッシュをリテラルとして指定するには、二重 (\\
) にします。 それ以外の場面で登場するバックスラッシュは、すべてバックスラッシュそのものとして扱われます。 つまり、\r
や\n
といったおなじみのエスケープシーケンスを書いても特別な効果は得られず、 書いたままの形式で出力されます。
文字列の指定に「’」を使っている時は
- 「\’」が「’」にエスケープされる
- 「\\」が「\」にエスケープされる
- 上記以外の「\」はすべてバックスラッシュそのものとして扱われる
とのことです。実際に確認してみました。
1> echo 'I\'ll be back';
2I'll be back
1> echo 'C:\\User';
2C:\User
1> echo 'end\n';
2end\n
確かに、記載の通りです。では「\’」を文字列として指定するにはどうすればよいでしょうか?
1> echo 'I\\'ll be back';
2 PARSE ERROR PHP Parse error: Syntax error, unexpected T_STRING, expecting ';' in vendor/psy/psysh/src/Exception/ParseErrorException.php on line 38.
上記だとエラーが出ました。「\\」が「\」にエスケープされて、「’」がそのまま文字列の最後の引用符と認識されてエラーになっているようです。正しくは以下のように書く必要があります。
1> echo 'I\\\'ll be back';
2I\'ll be back
続いて「”」についても公式ドキュメントを見ていきます。
二重引用符
二重引用符
文字列が二重引用符 (“) で括られた場合、 PHP は、以下のエスケープシーケンスを特殊な文字として解釈します。
記述 意味 \n
ラインフィード (LF またはアスキーの 0x0A (10)) \r
キャリッジリターン (CR またはアスキーの 0x0D (13)) \t
水平タブ (HT またはアスキーの 0x09 (9)) \v
垂直タブ (VT またはアスキーの 0x0B (11)) \e
エスケープ (ESC あるいはアスキーの 0x1B (27)) \f
フォームフィード (FF またはアスキーの 0x0C (12)) \\
バックスラッシュ \$
ドル記号 \"
二重引用符 \[0-7]{1,3}
8進数: 正規表現 [0-7]{1,3}
にマッチする文字シーケンスは、8 進数表記の 1 文字 (例:."\101" === "A"
) です。 正規表現にマッチする文字シーケンスは、8 進数表記の 1 文字です。 1 バイトに収まらない部分は、何もメッセージを出さずにオーバーフローします (例:"\400" === "\000"
) 。\x[0-9A-Fa-f]{1,2}
16進数: 正規表現 [0-9A-Fa-f]{1,2}
にマッチする文字シーケンスは、16 進数表記の 1 文字(例:"\x41" === "A"
)です。\u{[0-9A-Fa-f]+}
Unicode: 正規表現 [0-9A-Fa-f]+
にマッチする文字シーケンスは、Unicode のコードポイントです。 そのコードポイントの UTF-8 表現を文字列として出力します。 シーケンスを波括弧で囲む必要があります。例"\u{41}" === "A"
「’」と比較して、エスケープシーケンスが多いですね。こちらもいくつかピックアップして確認します。
1> echo "abc\ndef";
2abc
3def
1> echo "abc\tdef";
2abc def
1> echo "I\"ll be back";
2I"ll be back
一覧にあがっているパターン以外で「\」を使用した場合は、「’」と同じくそのまま出力されます。
以上、エスケープシーケンスの種類が「’」と「”」の違い一つ目でした。
変数のパースが発生するかしないか
二つ目の違いは、変数のパースが発生するかしないかです。
公式ドキュメントにはこのような記述がありました。
文字列が二重引用符で括られるかヒアドキュメントで指定された場合、 その中の変数はパースされます。
構文の型には、単純な構文と 複雑な 構文の 2 種類があります。簡単な構文は、最も一般的で便利です。 この構文では、変数や配列の値、オブジェクトのプロパティを、 簡単に文字列に埋め込むことができます。
複雑な構文は、式を波括弧で括ることにより認識されます。
「”」で文字列を指定する時、変数を使うと変換してくれるとのことです。確認してみましょう。
簡単な構文
公式ドキュメントの続きです。こちらの内容を確認してみます。
簡単な構文
ドル記号 (
$
) を見付けると、 パーサは、有効な変数名を形成することが可能な最長のトークンを取得します。 変数名の終りを明示的に指定したい場合は、変数名を波括弧で括ってください。
1> $sport = "baseball";
2= "baseball"
3
4> echo "He play $sport";
5He play baseball
6
7> echo "He play {$sport}s";
8He play baseballs
9
10> echo "He play $sports";// $sportsは定義していないので変換されない
11He play
変数を文字列に指定すると、変数に入れた値で出力してくれました。波括弧でくくるとその箇所だけ確認して変数を変換してくれますね。逆にくくらないと出力できません。
複雑な構文
こちらも公式ドキュメントで続きがあります。以下の内容を確認します。
複雑な (波括弧) 構文
この構文が「複雑(complex)な構文」と呼ばれているのは、 構文が複雑であるからではなく、 この方法では複雑な式を含めることができるからです。
どんなスカラー変数、配列の要素あるいはオブジェクトのプロパティの文字列表現であっても この構文で含めることができます。 文字列の外側に置く場合と同様に式を書き、これを { と } の間に含めてください。'{‘ はエスケープすることができないため、 この構文は $ が { のすぐ後に続く場合にのみ認識されます (リテラル “{$” を指定するには、”{\$” を使用してください)。
1> $array = [[1,2,3],[4,5,6],[7,8,9]];
2> echo "{$array[1][2]}"; // 多次元配列の要素
36
1> $array = [
2. 'first' => 1,
3. 'second' => 2,
4. 'third' => 3
5. ];
6> echo "His rank is {$array['first']}"; //連想配列の要素
7His rank is 1
1> class obj {
2var $prop = 'this is a pen';
3. }
4> $obj = new obj();
5> $prop = 'prop';
6> echo "{$obj->$prop}"; // オブジェクトのプロパティへ変数を使用してアクセス
7this is a pen
簡単な構文でも配列の要素やオブジェクトのプロパティを表現することはできます。しかしながら、上記であげたような配列やオブジェクトへのアクセスは、波括弧ありでのみ、表現が可能になるようです。
以上、変数のパースが発生するかしないかが、「’」と「”」の違い二つ目でした。
まとめ
「’」と「”」の違い二つについて解説していきました。
普段文字列の指定に使うのは「’」にしておいて、「”」にのみ存在する機能を使いたい時に「”」を使う形が、コードの読み手にも伝わりやすく良いと思います。もちろん、プロジェクトのコーディング規約が優先ですけどね。
今回の記事は以上にしたいと思います。ありがとうございました!