【On to PHP】シングル?ダブル?引用符?PHPの文字列いろいろ

こんにちは、さるまりんです。

On to PHPです。今回は文字列を表す記述についてスッキリしていきたいと思います。

文字列リテラルとは

文字列リテラルの説明を見ると

「0文字以上の連続した文字列を示す定数」

とあります。(上記はweblio辞書さんからの引用です。)

難しいですね〜。では具体的にはどんなものなのでしょうか。

以下は$nameという変数に僕の名前「さるまりん」を代入するコードです。

$name = 'さるまりん';

ここで$nameが文字列を持つ変数です。そしてその変数が持っている文字列が引用符(')に囲まれた部分、文字列自体が文字列リテラルです。

文字列は引用符で囲む

PHPで文字列リテラルを書くときには上の例のように文字列を引用符で囲みます。引用符には単一引用符(')(シングルクォート)と二重引用符(")(ダブルクォート)があります。いきなり横道にそれますがJavaなど他の言語では二重引用符のみが文字列リテラルを表記する際に使われることが多いのですが、PHPでは上の両方を使うことができます。

$name_in_s = 'さるまりん'; // シングル
$name_in_d = "さるまりん"; // ダブル

このどちらの書き方もOKです。

文字列に引用符を含むときはどうしましょう?簡単な方法は含みたい引用符とは違う方の引用符で囲むことで引用符を文字列に含むことができます。

$occupation = "I'm a programmer."; // シングルクォートを含みます。
$his_words = 'He said, "No way."'; // ダブルクォートを含みます。

こんな具合です。上の行では'の文字を含むために全体を"で囲み、下の行では"の文字を含むために'で全体を囲んでいます。

'"のどちらも含むときはどうしましょう?

エスケープシーケンス

I’m a “good” programmer.

こんな文字列を文字列リテラルとするときには文字列の中に含まれる引用符をエスケープすることで実現します。エスケープとは特別な意味をもつ文字を決められた方法で無効化することです。特別な意味を持つ文字というのはここでは"'がそれにあたります。ではその決められた方法とは何かというと特別な意味を持つ文字の前に\をおくことです。

上の文字列は次のように記述することができます。

$my_occupation = "I'm a \"good\" programmer.";

こんな感じです。'の前に\がないのは""で囲まれた文字列の中では'はそのままで含むことができるからです。

では今度は\を文字列に含みたいときはどうでしょう。それは\文字を2度続けて置くことで実現できます。

\Yeah/

という文字列を表すには次のように記述します。

$yeah = "\\Yeah/";

文字列の中で特別な意味のある文字をエスケープするときはバックスラッシュ(\)を使うということです。

単一引用符と二重引用符で囲む文字列の違い

先ほどPHPの文字列リテラルでは囲む文字に単一引用符と二重引用符のどちらも使えるということを書きましたがその違いはなんでしょう。

二重引用符で囲まれた文字列ではその中に含まれる変数が展開され、単一引用符ではされないという違いがあります。

$name = "さるまりん";
$hello = "こんにちは、僕は$nameです。";
print $hello;

上のプログラムでは1行目で変数$nameに僕の名前「さるまりん」を代入しています。そして2行目では変数$helloに挨拶の文をセットしています。そこの文字列の中に$nameが入っていますが、これがミソです。二重引用符で囲んだ文字列の中にはこのようにして変数を埋め込みその値を含むことができるのです。なので3行目のprintの命令では

こんにちは、僕はさるまりんです。

と出力されます。

例えば2行目を

$hello = 'こんにちは、僕は$nameです。';

とすると、3行目のprintの命令では

こんにちは、僕は$nameです。

とそのまま出力されます。単一引用符では変数の値は展開されません。

""の中に変数を含むときには{}で変数を囲むことができます。こんな具合です。

$hello = "こんにちは、僕は{$name}です。";

これはどこからどこまでが変数かをはっきりさせるためにこのような書き方をします。

例えば$name$name_version2という変数があったとします。このとき

"僕は$name_version2です"

と記述すると展開するべき変数が$nameなのか$name_version2なのか不明瞭です。そのため区切りがどこなのかをはっきりさせてるために{}で囲みます。

$name = "さるまりん";
$name_version2 = "さるまりんハイパー";
print "僕は{$name}_version2です"; // 僕はさるまりん_version2です
print "僕は{$name_version2}です"; // 僕はさるまりんハイパーです

それぞれコメントの部分が出力内容です。ちょっとしたことで違うんですね。

もう一つの違いはエスケープシーケンスの扱いです。エスケープシーケンスとはなんでしょう。これは先ほども少し出てきています。

引用符に囲まれた文字列の中で特別な意味を持つ文字をバックスラッシュ(\)を使って記述することができます。先ほど出てきました引用符、バックスラッシュの他にも「\文字」の形で表すことができる文字があります。よく使うものとして「\t」でタブ文字、「\n」で改行文字を表せます。二重引用符で囲まれた文字列の中ではこの書き方で表される文字が特別な意味をもち、単一引用符で囲まれた文字列の中ではそれらはそのままの状態で扱われます。

他にも

\nnn – nnn 3桁の8進数で表される文字(例えば\101はAの文字)

\xnn – nn 2桁の16進数で表わされる文字(例えば\41はAの文字)

\unnnn – nnnn 4桁の16進数で表されるUnicode文字(例えば\u0041はAの文字)

といったように\\x\uと数値を組み合わせて文字を表現することもできます。

(Unicodeについてはまたいずれ)

他のエスケープシーケンスのPHP本家のサイト文字列の項の二重引用符「エスケープされた文字」の一覧を参考にしてみてください。

繰り返しになりますが、これらは二重引用符で囲まれた文字列の中で有効です。

注意点ですが単一引用符で囲まれた文字列の中では\'\\の二つだけが有効でそれ以外はそのまま扱われます。逆に二重引用符で囲まれた文字列の中では\'は無効なのでそのまま扱われることになります。

ヒアドキュメント

もう一つ文字列リテラルを記述する方法があります。

これは改行を含む長い文字列を表す時に便利です。

例えばこんな文字列

こんにちは、僕はさるまりんです。
いつもプログラミングをしていますが
正直よくわからないことだらけです。
僕と一緒に勉強しませんか?

これまでのやり方ではこの文字列はエスケープシーケンスを使って次のように書くことができます。

$my_words = "こんにちは、僕はさるまりんです。\nいつもプログラミングをしていますが\n正直よくわからないことだらけです。\n僕と一緒に勉強しませんか?";

長いですよね。これをヒアドキュメントを使うとこんな風に書くことができます。

$my_words = <<<MYWORDS
こんにちは、僕はさるまりんです。
いつもプログラミングをしていますが
正直よくわからないことだらけです。
僕と一緒に勉強しませんか?
MYWORDS;

ここでは「<<<MYWORDS」から「MYWORDS;」の間が文字列リテラルとなります。

MYWORDSを最初と最後を示す区切りとして使っていますがこれは前と後ろが対応していれば有効な区切りとなります。TEXTでもLINESでもそれぞれ「<<<TEXT」と「TEXT;」、「<<<LINES」と「LINE;」のように始まりと終わりが一緒ならばOKです。

<<<MYWORDS」と「MYWORDS;」の間では引用符も好きなように使えます。またこの間に変数を置くとその値も展開されます。ちなみに開始の区切りを<<<'MYWORDSとすると文字列リテラルはシングルクォート(')で囲んだ時と同様に変数を展開せずやエスケープシーケンスはそのまま扱われることになります。

駆け足で文字列リテラルについてみてきました。

改めて見てくると文字列の書き方にもいろいろありました。

それぞれ場面によって使い分けていますが、シンプルにシングルクォートとダブルクォートの使い分けはどうしましょう。これはルールではありませんが、僕の場合は展開される変数やエスケープシーケンスがある時は二重引用符を使い、それ以外では単一引用符を使うようにしています。特別な意味がある文字を含むときだけ二重引用符といった具合です。

これがいい理由もわからないですが、スッキリ書けるように感じています。

なんでだろう?また理由考えてみます。

次はデータの型と変換かな。

読んでくださってありがとうございます。

それではまた!

Onto PHP 目次