【PHP入門】おみくじの抽選ロジックをサーバー側に移してみる
章: 1章
技術タグ: DevTools fetch GET JavaScript JSON Laragon PHP
今回やること
前回は、DevToolsを使って、ブラウザ側の中身が見えることを体験しました。
JavaScriptの処理やHTMLの表示は、ユーザーの手元で確認でき、一部は書き換えられます。
そこで今回は、おみくじの抽選ロジックをJavaScriptからPHPへ移します。
JavaScriptだけで結果を決めるのではなく、サーバー側であるPHPに抽選を担当させます。
前回まで: JavaScriptがブラウザ側で抽選する 今回: JavaScriptがPHPへリクエストする PHPがサーバー側で抽選する PHPが結果をJSONで返す JavaScriptが結果を画面に表示する
ここから、ブラウザだけで動くアプリから、サーバーと通信するWebアプリへ進みます。
今回のゴール
今回のゴールは、以下です。
- Laragon上でPHPが動く環境を用意する
- HTML・CSS・JavaScript・PHPの4ファイル構成にする
- PHP側でおみくじ結果をランダムに決める
- PHPからJSON形式で結果を返す
- JavaScriptのfetchでPHPへ通信する
- 返ってきた結果を画面に表示する
今回のポイントは、JavaScriptから抽選ロジックを消すことです。
JavaScriptは結果を決める係ではなく、PHPへ結果を取りに行く係になります。
今回必要なもの
今回はPHPを使うので、Live Serverだけでは足りません。
Live ServerはHTML・CSS・JavaScriptの確認には便利ですが、PHPを実行するためのサーバーではありません。
今回はLaragonを使う前提で進めます。
- VS Code
- Google Chrome
- Laragon
- Chrome DevTools
Laragonを使うと、ローカルPC上でPHPやMySQLを動かせます。
今回はMySQLはまだ使いません。まずはPHPだけを動かします。
Laragonでプロジェクトを作る
Laragonの www フォルダの中に、今回のプロジェクトフォルダを作ります。
フォルダ名の例は以下です。
omikuji-php
Laragonの設定によって多少違いますが、たとえば以下のような場所になります。
C:\laragon\www\omikuji-app
この中に、今回使うファイルを作ります。
omikuji-app/
├─ index.html
├─ style.css
├─ script.js
└─ omikuji.php
Laragonを起動している状態なら、ブラウザで以下のようなURLからアクセスできます。
http://omikuji-app.test環境によっては http://localhost/omikuji-app/ のようなURLになる場合もあります。omikuji-appフォルダを作ったら念のためLaragonを再起動しましょう。
ファイル構成
今回のファイル構成は以下です。
omikuji-php/ ├─ index.html ├─ style.css ├─ script.js └─ omikuji.php
| ファイル | 役割 |
|---|---|
| index.html | 画面の骨組みを作る |
| style.css | 見た目を整える |
| script.js | PHPへ通信して結果を表示する |
| omikuji.php | サーバー側でおみくじ結果を決める |
第1話では、JavaScriptの中におみくじ結果の配列がありました。
今回は、その配列をPHP側へ移します。
index.htmlを用意する
まずはHTMLです。
第1話とほぼ同じですが、タイトルをPHP版にしておきます。
index.html に以下を書きます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PHP版おみくじアプリ</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<main class="omikuji">
<h1 class="omikuji__title">PHP版おみくじアプリ</h1>
<p id="result" class="omikuji__result">結果はここに表示されます</p>
<button id="draw-button" class="omikuji__button" type="button">
おみくじを引く
</button>
</main>
</body>
</html>読み込み系は head にまとめ、JavaScriptには defer を付けています。
この方針なら、body には画面に表示する中身だけを書けます。
style.cssを用意する
CSSは第1話と同じで大丈夫です。
今回の主役はPHPと通信なので、見た目は作り込みません。
style.css に以下を書きます。
body {
margin: 0;
font-family: sans-serif;
background-color: #f5f5f5;
color: #222222;
}
.omikuji {
max-width: 480px;
margin-inline: auto;
padding-block: 64px;
padding-inline: 24px;
text-align: center;
}
.omikuji__title {
margin-block-start: 0;
margin-block-end: 24px;
font-size: 32px;
}
.omikuji__result {
margin-block-start: 0;
margin-block-end: 24px;
padding-block: 24px;
padding-inline: 16px;
border: 2px solid #222222;
border-radius: 12px;
background-color: #ffffff;
font-size: 24px;
font-weight: bold;
}
.omikuji__button {
padding-block: 12px;
padding-inline: 24px;
border-width: 0;
border-radius: 999px;
background-color: #222222;
color: #ffffff;
font-size: 16px;
font-weight: bold;
cursor: pointer;
}
.omikuji__button:hover {
opacity: 0.8;
}PHPでおみくじ結果を決める
ここからPHPです。
omikuji.php を作成し、以下を書きます。
<?php
/**
* omikuji.php
*
* 役割:
* - サーバー側でおみくじ結果をランダムに決める
* - 結果をJSON形式でブラウザへ返す
*/
$fortunes = ['大吉', '中吉', '小吉', '吉', '凶'];
$random_index = array_rand($fortunes);
$selected_fortune = $fortunes[$random_index];
$response = [
'fortune' => $selected_fortune,
];
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE);このPHPファイルの役割は、サーバー側でおみくじ結果を決めて、JSON形式で返すことです。
JavaScriptではなく、PHP側に以下の配列を持たせています。
大吉 中吉 小吉 吉 凶
つまり、おみくじ結果の候補はブラウザ側のJavaScriptではなく、サーバー側のPHPに移りました。
PHPコードの中身を分解する
まず、結果候補を配列で用意しています。
$fortunes = ['大吉', '中吉', '小吉', '吉', '凶'];
次に、array_rand() で配列のキーをランダムに1つ選びます。
$random_index = array_rand($fortunes);
選ばれたキーを使って、実際のおみくじ結果を取り出します。
$selected_fortune = $fortunes[$random_index];
その結果を、ブラウザへ返すための配列に入れます。
$response = [
'fortune' => $selected_fortune,
];
最後に、JSONとして返すためのヘッダーを指定し、json_encode() で出力します。
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE);
JSON_UNESCAPED_UNICODE を付けると、日本語が読みやすい形で返りやすくなります。
omikuji.phpだけをブラウザで開いてみる
まずはJavaScriptとつなぐ前に、PHPだけを確認します。
ブラウザで以下のようなURLを開きます。
http://omikuji-php.test/omikuji.php
うまくいけば、次のようなJSONが表示されます。
{"fortune":"大吉"}
更新するたびに、大吉、中吉、小吉 などが変われば成功です。
この時点で、PHP側で抽選できていることが確認できます。
JavaScriptからPHPへ通信する
次に、JavaScriptから omikuji.php へ通信します。
script.js を以下の内容にします。
const resultText = document.getElementById('result');
const drawButton = document.getElementById('draw-button');
/**
* PHP側におみくじ結果を取りに行き、画面へ表示する
*
* @returns {Promise<void>}
*/
async function drawFortune() {
resultText.textContent = '抽選中...';
try {
const response = await fetch('omikuji.php');
if (!response.ok) {
resultText.textContent = '通信に失敗しました';
return;
}
const data = await response.json();
resultText.textContent = data.fortune;
} catch (error) {
resultText.textContent = 'エラーが発生しました';
console.error(error);
}
}
drawButton.addEventListener('click', drawFortune);今回から、JavaScriptの中にはおみくじ結果の配列がありません。
JavaScriptは、PHPへリクエストして、返ってきた結果を画面に表示するだけです。
fetchとは何か
fetch() は、JavaScriptからサーバーへ通信するための機能です。
今回のコードでは、次の部分でPHPへリクエストしています。
const response = await fetch('omikuji.php');
これは、JavaScriptから omikuji.php に対して「結果をください」とお願いしているようなものです。
PHPはサーバー側で抽選をして、JSONを返します。
JavaScriptは、そのJSONを受け取って画面に表示します。
JavaScript ↓ fetch omikuji.php ↓ JSON JavaScript ↓ 画面に表示
response.json()でJSONを読む
PHPから返ってくるデータはJSON形式です。
JavaScript側では、次のコードでJSONを読み取ります。
const data = await response.json();
今回PHPから返ってくるJSONは、たとえば次のような形です。
{"fortune":"大吉"}
そのため、JavaScriptでは data.fortune で結果を取り出せます。
resultText.textContent = data.fortune;
これで、PHPが決めた結果を画面へ表示できます。
エラー処理も少しだけ入れておく
通信は、必ず成功するとは限りません。
ファイル名を間違えたり、PHP側でエラーが出たりすると、通信に失敗します。
そのため、今回は最低限のエラー処理も入れています。
if (!response.ok) {
resultText.textContent = '通信に失敗しました';
return;
}
さらに、予期しないエラーに備えて try...catch も使っています。
try {
// 通信処理
} catch (error) {
resultText.textContent = 'エラーが発生しました';
console.error(error);
}
最初は少し難しく見えるかもしれませんが、通信するコードではエラー時の逃げ道を作っておくのが大事です。
今回の流れを整理する
今回の処理の流れはこうです。
1. ユーザーがボタンを押す 2. JavaScriptのdrawFortune()が動く 3. fetchでomikuji.phpへ通信する 4. PHPがおみくじ結果をランダムに決める 5. PHPがJSONで結果を返す 6. JavaScriptがJSONを読む 7. 画面に結果を表示する
第1話では、JavaScriptが抽選も表示も担当していました。
今回からは、役割が分かれました。
| 担当 | 役割 |
|---|---|
| JavaScript | ボタンクリックを受け取り、PHPへ通信し、結果を画面に表示する |
| PHP | サーバー側でおみくじ結果を決め、JSONで返す |
この役割分担が、Webシステム開発の入口です。
DevToolsのNetworkで通信を見てみる
ボタンを押したら、DevToolsのNetworkタブも見てみましょう。
Networkタブを開いた状態でおみくじボタンを押すと、omikuji.php への通信が見えるはずです。
ここでは、次のことを確認できます。
- JavaScriptがomikuji.phpへリクエストしている
- PHPからJSONが返ってきている
- 返ってきたJSONの中にfortuneが入っている
今回の時点では、Networkを完璧に理解しなくて大丈夫です。
まずは「ボタンを押すと、裏側でPHPに通信している」という事実を目で確認できれば十分です。
今回わかったこと
今回は、おみくじの抽選ロジックをJavaScriptからPHPへ移しました。
学んだことは以下です。
- Live ServerだけではPHPは動かない
- PHPを動かすにはLaragonなどのローカル環境が必要
- PHP側で配列からランダムに結果を選べる
- PHPはJSON形式で結果を返せる
- JavaScriptはfetchでPHPへ通信できる
- JavaScriptは返ってきたJSONを読んで画面に表示できる
- 重要なロジックはブラウザ側ではなくサーバー側に置く考え方がある
これで、ブラウザだけで動くアプリから、サーバーと通信するWebアプリへ一歩進みました。
ただし、これで完璧に安全というわけではない
今回、抽選ロジックをPHPへ移したことで、JavaScript側におみくじ結果の配列を置かなくなりました。
これは前回より良い構成です。
しかし、これだけで完璧に安全というわけではありません。
本気のキャンペーンやログインが絡む処理では、さらに次のような対策も必要になります。
- 同じ人が何度も引けないようにする
- 結果をデータベースに保存する
- 不正な連続アクセスを防ぐ
- ユーザーごとの状態を管理する
- サーバー側で最終判定する
今回の目的は、まず「重要な処理をサーバー側へ移す」という考え方を体験することです。
一歩ずつ進めば大丈夫です。
次回予告
次回は、DevToolsのNetworkタブを使って、今回の通信をもう少し詳しく観察します。
ボタンを押した時に、ブラウザからPHPへどんなリクエストが飛び、PHPからどんなレスポンスが返ってくるのかを見ます。
次回のテーマは、以下です。
【DevTools Network入門】fetch通信でPHPから返るJSONを見てみる
Webアプリは、画面だけでなく通信も見ると一気に理解が進みます。
次回は、ブラウザとサーバーの会話を覗いていきます。