PHP で複数の値を連結して echo する時のちょっとした tips

PHP で複数の値を連結して出力する際に, 以下のように `.` (ドット) で連結して echo する方は結構多いのではないでしょうか？ (自分も最近までそうしてました)

例えばこんな風に.

```php
<?php
$name = "Taro";
$age  = 18;

echo "Name: " . $name . " Age: " . $age . PHP_EOL;
```

しかしこのコードは以下のように `,` (カンマ) で連結して書くこともできます.

```php
<?php
$name = "Taro";
$age  = 18;

echo "Name: ", $name, " Age: ", $age, PHP_EOL;
```

## ドットとカンマの違い

上の 2 つのコードは出力結果が同じですが, 前者と後者でコードの意味が違います.

### ドットを使う場合

```php
<?php
echo $a . $b . $c;
```

1. `$a` と `$b` と `$c` を連結した文字列を新しく作成する
2. 作成した文字列を echo する

わざわざ解説するまでもないですが, 文字列連結演算子を使って複数の文字列を連結し, その結果を echo しています.

### カンマを使う場合

```php
<?php
echo $a, $b, $c;
```

1. `$a` を echo する
2. `$b` を echo する 
3. `$c` を echo する

という具合に, 複数の echo 文を並べるのと同じ意味になります.

## どちらを使うべきか？

特別な事情 [^1] がなければカンマを使ったほうが良いと思います. 例えば大量の文字列を返す関数呼び出しの結果を連結する場合を考えてみましょう.

```php
<?php
echo very_long_string_generator1() . very_long_string_generator2() . very_long_string_generator3();
```

このコードは, 以下のような動作をします.

1. very_long_string_generator1(), very_long_string_generator2(), very_long_string_generator3() の結果をそれぞれ文字列で取得する
2. 1. で生成した3 つの文字列を連結して新しい文字列を生成する
3. 2. で生成した文字列を echo する

この挙動だと, 1. で巨大な文字列を 3 つ取得した後, さらにそれらを連結した新しい文字列を生成するわけで, メモリを大量に消費してしまいます.

一方で

```php
<?php
echo very_long_string_generator1(), very_long_string_generator2(), very_long_string_generator3();
```

このコードの場合だと

1. very_long_string_generator1() の結果を出力する
2. very_long_string_generator2() の結果を出力する
3. very_long_string_generator3() の結果を出力する

という具合に, 文字列を連結するのではなく随時出力するのでメモリの無駄がありません.

### レガシーな環境ではこんな利点が

PHP のクラスは `__toString` というメソッドを定義することで, そのクラスを好きなフォーマットで文字列として表現することが出来ます.

```php
<?php
class Hoge
{
    public function __toString()
    {
        return "My Hoge class";
    }
}

$obj = new Hoge();
echo $obj; // My Hoge class
```

ところがオブジェクトと文字列を連結した場合, PHP 5.1 系では `__toString()` が使われないという仕様があります.

```php
<?php
class Hoge
{
    public function __toString()
    {
        return "My Hoge class";
    }
}

$obj = new Hoge();
echo "I am " . $obj . PHP_EOL;
```

このコードの PHP のバージョン毎の出力結果は以下の通りです.

```
5.1.1
I am Object id #1

5.1.6
I am Object id #1

5.2.0
I am My Hoge class

5.2.17
I am My Hoge class

5.3.0
I am My Hoge class

5.3.28
I am My Hoge class

5.4.0
I am My Hoge class

5.4.37
I am My Hoge class

5.5.0
I am My Hoge class

5.5.21
I am My Hoge class

5.6.0
I am My Hoge class

5.6.5
I am My Hoge class
```

PHP 5.2.0 以降は Hoge クラスの __toString() が参照されて `I am My Hoge class` と出力されていますが PHP 5.1 系のみ `I am Object id #1` になってしまうことが分かります.

ところがカンマを使った場合だと

```php
<?php
class Hoge {
    public function __toString()
    {
        return "My Hoge class";
    }
}

$obj = new Hoge();
echo "I am ", $obj, PHP_EOL;
```

```
5.1.1
I am My Hoge class

5.1.6
I am My Hoge class

5.2.0
I am My Hoge class

5.2.17
I am My Hoge class

5.3.0
I am My Hoge class

5.3.28
I am My Hoge class

5.4.0
I am My Hoge class

5.4.37
I am My Hoge class

5.5.0
I am My Hoge class

5.5.21
I am My Hoge class

5.6.0
I am My Hoge class

5.6.5
I am My Hoge class
```

ご覧の通り PHP 5.1.1 から PHP 5.6.5 までのすべてのバージョンで同じ結果になることが確認できました. (※スペースの都合でその他のバージョンは端折っています)

CentOS 5 系 + PHP 5.1.6 みたいなインフラで現役稼働しているシステムもまだまだあるのではと思いますが, レガシーな環境の保守などで是非活用いただければと思います.

## 関連記事

* [echoとprintの違い](https://qiita.com/tadsan/items/e09475093bc336881b20)

[^1]: 例えば [出力制御関数](http://jp.php.net/manual/ja/ref.outcontrol.php) を使って echo の挙動を意図的にカスタマイズしている場合など