PHPはサーバーで動きます。ページを組み立て、完成したHTMLを送って終了します。JavaScriptは訪問者のブラウザで動き、クリックに反応して、読み込みが終わったあとのページを変更します。Node.jsを使えばサーバーでも動きます。つまり2つはライバルというよりパートナーで、典型的なサイトはサーバーでPHP(またはNode.js)を、ブラウザでJavaScriptを使います。
このPHPコードはサーバーで動きます。ブラウザが受け取るのは出力された内容だけで、Pageタブにはその結果が表示されます。
Outputタブを見てください。PHPは何も残っておらず、HTMLだけです。同じリストをブラウザのJavaScriptで作ると次のようになります。
const products = [
{ name: "Keyboard", price: 49 },
{ name: "Mouse", price: 19 },
{ name: "Monitor", price: 189 },
];
const ul = document.querySelector("#cart"); // an empty <ul id="cart"> in the HTML
for (const p of products) {
const li = document.createElement("li");
li.textContent = `${p.name}: $${p.price}`;
ul.append(li);
}
PHP版は完成したページを送るので、検索エンジンや遅いスマートフォンでもすぐに読めます。JavaScript版は、たとえば訪問者が商品を削除したときなどに、再読み込みせずにあとからリストを更新できます。
それぞれの言語が動く場所
| PHP | JavaScript | |
|---|---|---|
| 動く場所 | Webサーバー(またはターミナル) | ブラウザ、およびNode.js、Deno、Bunでのサーバー |
| 扱えるもの | ファイル、データベース、環境変数、秘密情報 | ページ(DOM)、クリック、ブラウザのストレージ |
| 存続期間 | リクエストごとに1回実行 | ページが開いている間(ブラウザ)、または1つの常駐プロセス(Node.js) |
| 典型的な役割 | ページの生成、フォーム処理、API、データベースとのやり取り | インタラクション、リアルタイム更新、SPA、Node.jsのサーバー |
| 訪問者がコードを読めるか | 読めない | ブラウザで読める |
最後の行はセキュリティ上重要です。ブラウザのJavaScriptにあるものはすべて訪問者に見えるので、パスワード、APIキー、価格のチェックはサーバーに置くべきです。
文法を並べて比較
2つの言語はどちらもCから借りているので見た目が似ています。波括弧、if、for、while、function、returnです。違いは細部にあります。
| 処理 | PHP | JavaScript |
|---|---|---|
| 変数 | $name = "Ada"; | let name = "Ada"; |
| 定数 | const MAX = 10; | const MAX = 10; |
| 文字列の連結 | "Hi " . $name | "Hi " + name |
| テンプレート文字列 | "Hi $name" | `Hi ${name}` |
| リスト | ["a", "b"] | ["a", "b"] |
| キーと値 | ["id" => 1] | { id: 1 } |
| 長さ | count($list), strlen($s) | list.length, s.length |
| ループ | foreach ($list as $item) | for (const item of list) |
| アロー関数 | fn($x) => $x * 2 | (x) => x * 2 |
| 出力 | echo "Hi"; | console.log("Hi"); |
PHPでコールバックを使う関数の例です。
JavaScriptではmapとfilterは配列のメソッドです。
const prices = [12.5, 8, 30, 4.25];
const withTax = prices.map((p) => Math.round(p * 1.2 * 100) / 100);
const cheap = withTax.filter((p) => p < 15);
console.log(withTax.join(", "));
console.log("Under 15: " + cheap.join(", "));
+演算子:定番の罠
JavaScriptの+は数値の足し算と文字列の連結の両方を行うので、どこかに文字列があると足し算が連結に変わります。PHPは2つを分けていて、+は常に足し算、.は常に連結です。
console.log("10" + 5); // "105"
console.log("10" - 5); // 5
console.log("3" * "4"); // 12
console.log(0.1 + 0.2 === 0.3); // false
どちらの言語にもゆるい==と厳密な===があります。アドバイスもどちらも同じで、型をまたいで比較するつもりがなければ===を使います。
PHPからJavaScriptにデータを渡す
PHPが先に動くので、ブラウザのJavaScriptが使うデータをページに直接書き込めます。json_encodeはPHPの配列を正しいJavaScriptに変換します。
Outputタブには、データが埋め込まれた状態で生成されたスクリプトが表示されます。JSON_HEX_TAGフラグは<と>をエスケープするので、</script>を含む値があってもスクリプトが途中で終わることはありません。オプションについてはjson_encodeで詳しく説明しています。
逆方向はHTTPで行います。ブラウザのJavaScriptがfetch("/api/cart.php")を呼ぶとPHPスクリプトが実行され、JSONで応答します。
<?php
// api/cart.php
header('Content-Type: application/json');
echo json_encode(['items' => 3, 'total' => 257]);
const res = await fetch("/api/cart.php");
const cart = await res.json();
console.log(cart.total); // 257
サーバー側のPHPとNode.js
JavaScriptがNode.jsでサーバー上で動く場合、比較は本当の選択になります。
| PHP | Node.js | |
|---|---|---|
| モデル | リクエストごとにまっさらな実行、何も共有しない | イベントループを持つ1つの常駐プロセス |
| I/Oの待ち | そのリクエストをブロックする(ほかのリクエストは別のワーカーで動く) | ノンブロッキング、async/await |
| 得意なこと | サーバーで描画するサイト、CMS、定番のCRUDアプリ | リアルタイムアプリ、WebSocket、多数の待機中の接続 |
| ホスティング | どのレンタルサーバーでも、PHP-FPM | Nodeのプロセスマネージャー、またはVercelなどのプラットフォーム |
| 主なフレームワーク | Laravel、Symfony、WordPress | Express、NestJS、Next.js |
| フロントとバックを1つの言語で | できない | できる |
PHPのモデルは寛容です。バグやメモリリークの影響は1つのリクエストにとどまり、各リクエストはきれいな状態で始まります。Nodeのモデルは状態や接続を保持し続けられるのでチャットやリアルタイムのダッシュボードに向いていますが、クラッシュやブロッキングするループはそのプロセスの全ユーザーに影響します。
どちらを学ぶか
インタラクティブなWebページには必ずJavaScriptが必要です。ブラウザが実行する唯一の言語だからです。問題はサーバーで何を動かすかです。
- 次にPHPを学ぶ: WordPressやLaravel、数多くある既存のPHPサイトに関わりたい場合や、安価なサーバーで動的なサイトをいちばん簡単に公開したい場合。まずはPHPとはから始めてください。
- JavaScript(Node.js)を続ける: スタック全体を1つの言語で書きたい場合や、リアルタイムの機能を作る場合。
よくある道筋は、HTMLとCSS、次にブラウザのJavaScript、そしてサーバー言語を1つ、という順番です。どのサーバー言語を選んでも、フォーム、セッション、データベース、JSONのAPIは同じHTTPの考え方で動くので、知識はそのまま活かせます。
よくある質問
JavaScriptはPHPの代わりになりますか?
サーバー側ならなります。Node.js(Express、Next.jsなど)はPHPと同じ仕事をこなします。ブラウザ側では、ブラウザはJavaScriptしか実行しないので、PHPがJavaScriptの代わりになることはまったくできません。だから多くのサイトは、サーバーでPHPかNode、ブラウザでJavaScriptを使っています。
PHPの変数をJavaScriptに渡すには?
JSONとしてページに出力します:<script>const user = <?= json_encode($user, JSON_HEX_TAG) ?>;</script>。json_encodeは文字列、数値、配列、オブジェクトを正しいJavaScriptとして出力し、JSON_HEX_TAGはデータ内の</script>がタグを閉じてしまうのを防ぎます。
JavaScriptからPHPの関数を呼べますか?
直接は呼べません。PHPはサーバーで、JavaScriptはブラウザで動くからです。JavaScriptがfetch('/api.php?id=3')でHTTPリクエストを送り、PHPスクリプトが実行されてレスポンス(たいていJSON)を出力し、JavaScriptがそれを読みます。
PHPはNode.jsより速いですか?
処理の内容によります。Node.jsはイベントループのおかげで、同時に多数の遅い接続(チャット、WebSocket)を扱うのが得意です。OPcacheを使ったPHP 8は、通常のリクエストとレスポンスのページで高速です。ほとんどのサイトでは、ボトルネックは言語ではなくデータベースです。