Help us understand the problem. What is going on with this article?

echoとprintの違い

PHPのechoprintはどちらも関数ではなく言語構造です。どちらも文字列を出力バッファに書き出すという機能では同じですが、使われかたが異なります。

echo 1, 2, 3; // ← syntax error ではない
print 1, 2, 3; // ← これは syntax error

echo print 1; // ← syntax error ではない
print echo 1; // ← これは syntax error

形式的に言うと

  • echoprintはどちらも出力バッファに書き込む機能です
    • まれに「標準出力する」と言及されますが、それは間違いです
    • fwrite(STDOUT, $str)の実行結果とは一致しないということです
  • echoは文ですがprintは式です
  • echoは複数の引数をとりますが、printは1つの引数をとります
  • 便宜上関数マニュアルに掲載されているが関数ではありません

どれを使えばいいの?

好みで何を使ってもいいと思うのですが、printを使うメリットは特にないのでechoを薦めます。

echo $string;

または

echo $str1, $str2, PHP_EOL;

この形式だけを使えばいいと思います。

また、 echoprintはどちらも関数ではないので echo($v)print($v)のような関数呼び出し風の記述は誤解を呼ぶので使わない方が良いと思います。

echo

https://www.php.net/echo

echo — 1 つ以上の文字列を出力する

print との主な違いは、 echo がリスト形式の引数を受け付け、返り値を持たないことです。

たしかにPHPの文は式の項にならない(値を返さない)ので、説明通りです。

まれにechoを関数のように呼び出すひとがいます。

echo("str");

しかし、この ()$i = 1 + 2; と書いても $i = (1 + 2);と書いても結果が変わらないのと同じで、余分なカッコを書いているだけです。

これで、以下のような式がsyntax errorになることを説明できます。

echo("str1", "str2");

これは関数呼び出しで例えると f(1, 2) と書くべきものを f((1, 2)) と書いていることと同じです。PHPには関数呼び出しや言語構造の引数以外に(1, 2)のように値を列挙する式はありません。

print

https://www.php.net/print

print — 文字列を出力する

echoとの主な違いは、printが単一の引数のみ受け付け、常に 1 を返すことです。

この説明からはわかりにくいですが、printは式であり、式の中に書くことができるということです。

どうしてわざわざ、echoとは異なるこのような仕様があるのでしょうか。

わたしが考えつく限り、この仕様のユースケースは以下のようなものです。

foo() and print "success\n";
bar() or print "error\n";

これらの式はifを使って以下のように書き直せます。

if (foo()) {
    echo "error", PHP_EOL;
}

if (!bar()) {
    echo "error", PHP_EOL;
}

これらは、わざわざショートコーディングを正当化するためには心許ない例です。書き捨てのコードでデバッグ用途で一瞬使うだけならともかく、もっとわかりやすく書いた方がよいでしょう。

printは関数呼び出しではなく言語構造なので、print(1)と書いても(print 1)と書いても同じことです。print(1, 2)と書いてしまうと関数呼び出しのように錯覚させてしまいますが、これは関数呼び出し式ではないため、純粋にsyntax errorです。

printf()

せっかくなのでprintf()にも言及しておきましょう。echoprintは言語構造でしたが、printf()はPHPの組み込み関数です。

https://www.php.net/printf

printf — フォーマット済みの文字列を出力する

これも出力バッファに文字列を書き出すという意味では共通していますが、意味が異なります。echoprintが単に文字列を出力するだけのものであるのに対して、printf()はフォーマット文字列を整形する、一種のテンプレートエンジンと呼べるものです。

printf('%d + %d = %d', $a, $b, $a + $b);

printf()は高機能なので活用すると便利ですが、echoprintとは違う使いかたを意識する必要があります。

// 安全なコード
echo "こんにちは {$name} さん! ({$num}回め)";

// 危険なコード
printf("こんにちは {$name} さん! (%d回め)", $num);

後者のコードでは$name%が含まれると実行時エラーやテンプレートの位置をずらされるといった問題が起きえます。sprintf()を使って文字を組み立てる場合などもバグや脆弱性の原因となりうることがあるでしょう。

printf("こんにちは %s さん! (%d回め)", $name, $num);

printf()sprintf()などの第一引数には変数を直接展開せず、printf()%sなどを使ってください。

オペコードとの関係

PHP5時代はオペコードレベルでPRINTECHOは別の命令でしたが、PHP7ではECHO命令に統合されており最適化も施されるので特に違いは生じないはずです。

2015年9月に出版されたPHPはどのように動くのか ~PHPコアから読み解く仕組みと定石ではprintよりもechoの方がパフォーマンスに優れていると読み取れる記述があるのですが、実際には2015年12月にはPHP 7.0がリリースされており、実態にそぐわない記述になってしまいました。

読者への課題

PHP-Parserを使って、以下のようなソースコードを生成してみましょう。

<?php

echo 1;
print 2;
tadsan
僕に警備する自宅をください。Emacs初心者。Rubyist。 全ての投稿された記事は別段の表記がない限りはCC 3.0 BY-SA https://creativecommons.org/licenses/by-sa/3.0/deed.ja で二次利用できます。 記事中に含まれる全てのコードスニペットの著作権は抛棄するので、煮るなり焼くなりお好きにどうぞ。
https://tadsan.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした