PHPとデータベースで作る星占い

PHPとデータベースを使って星占いページを作成しましょう。

完成イメージ

フォルダ構成とファイル名

  • 作成フォルダ:php-practice-zodiac作成ファイル:z_list.php
  • 使用CSSファイル(任意):style.cssは任意で作成

データベーステーブルの作成

下記の仕様書を元にtestdbにzodiacテーブルを作成しましょう。

CREATE TABLE zodiac (
  id INT AUTO_INCREMENT PRIMARY KEY,
  score INT(4) NOT NULL,
  sign VARCHAR(30) NOT NULL,
  fortune TEXT NOT NULL,
  lucky_color CHAR(7) NOT NULL,
  color_name VARCHAR(10) NOT NULL,
  image VARCHAR(255) NOT NULL
);

下記のCSVファイルをインポートします。エクセルで作成し、CSVに書き出すことで毎月の更新が楽になります。

1,100,おひつじ座,エネルギッシュな月です。新しいことに挑戦することで運気がさらにアップ。積極的な行動が吉です。人との出会いにも恵まれそう。少し背伸びする挑戦が開運のカギ。,#dd2727,赤,ohitsuji.png
2,67,おうし座,落ち着いて過ごせる月です。生活リズムを整えることで心身ともに充実。計画的に物事を進めると良い成果が得られます。自宅の整理整頓も運気アップ。,#228b22,緑,oushiza.png
3,61,ふたご座,コミュニケーション運が絶好調。情報交換やSNSで新しいアイデアが生まれます。外に出て人と関わると運が開けます。意見交換がラッキーアクション。,#ffd700,金色,futagoza.png
4,77,かに座,家族や身近な人との時間を大切にすると心が満たされる月。家の中の模様替えや整理整頓も吉。気分がスッキリして新しい一歩が踏み出せます。,#ffffff,白,kaniza.png
5,75,しし座,注目が集まる月。自信を持って行動すると周囲からの評価が高まります。リーダーシップを発揮してみましょう。積極的に発言するとさらに吉。,#ffa500,オレンジ,shishiza.png
6,74,おとめ座,細かい作業や整理整頓がはかどる月。勉強や資格取得に集中するのもおすすめ。健康管理にも気を配ると良い結果に。早寝早起きが開運ポイント。,#87ceeb,空色,otomeza.png
7,68,てんびん座,人間関係が活発になる月。新しい出会いやコラボが生まれそう。バランス感覚を活かして調整役になると運気アップ。感謝の言葉を伝えると良い流れに。,#ff69b4,ピンク,tenbinza.png
8,66,さそり座,深い対話や研究が吉。じっくり物事に向き合うと良い成果が出ます。感情の整理も進めて心のデトックスを。夜の散歩がひらめきを呼びます。,#000000,黒,sasoriza.png
9,94,いて座,行動力が試される月。旅行や新しい挑戦にツキがあります。やりたいことに素直に飛び込むと成長につながります。アウトドア活動が吉。,#1e90ff,青,iteza.png
10,65,やぎ座,努力が実を結ぶ月。コツコツと取り組んできたことが形になります。責任感を持って最後までやり抜きましょう。計画表を見直すと効果的。,#8b4513,茶色,yagiza.png
11,97,みずがめ座,独創的なアイデアが浮かぶ月。新しいプロジェクトや提案に挑戦すると良い結果に。自由な発想がカギです。ノートにアイデアを書き留めて吉。,#800080,紫,mizugameza.png
12,87,うお座,感受性が豊かになる月。芸術や音楽に触れると心が満たされます。人の優しさに触れて癒される瞬間も多そうです。映画鑑賞がおすすめ。,#191970,紺,uoza.png

星占い最初の画面

z-list.phpの作成手順

  • データベースに接続(common.phpを作成)
  • SELECT id, sign,image FROM zodiac ORDER BY idで取得したデータを配列に入れ表示
  • 一覧ページからのリンク(GETパラメータを使った遷移します)
<?php
require 'common.php';

$sql = $pdo->query('SELECT id, sign, image FROM zodiac ORDER BY id');
$signs = $sql->fetchAll(PDO::FETCH_ASSOC);
?>
z-list.phpの例
<?php
require 'common.php';

$sql = $pdo->query('SELECT id, sign,image FROM zodiac ORDER BY id');
$signs = $sql->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>星占い一覧</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div class="content">
        <h1>星座を選んでください</h1>
        <ul class="list">
            <?php foreach ($signs as $s): ?>
                <li>
                    <a href="z_show.php?id=<?= h($s['id']) ?>">
                        <div>
                            <img src="img/<?= h($s['image']) ?>" alt="<?= h($s['sign']) ?>">
                        </div>
                        <div>
                            <?= h($s['sign']) ?>
                        </div>
                    </a>
                </li>
            <?php endforeach; ?>
        </ul>
    </div>
</body>

</html>

各星座名をクリックし、星占いを表示

各星座名をクリックすると、その星座の運勢を表示するページを作成します。
表示させたい画像は、あらかじめ img/ フォルダに用意し、
データベーステーブルの image カラムに登録したファイル名と合わせておきましょう。

完成イメージ

z-show.php の作成手順

  1. common.php を読み込み、データベース接続
  2. URLパラメータ id を取得
    $_GET['id'] ?? 0 で取得、無ければ 0 にしておく
  3. データベースから該当の星座を1件取得
  4. HTMLに埋め込んで表示
    • 画像 (image カラム)
    • 星座名 (sign カラム)
    • 運勢 (fortune カラム)
    • ラッキーカラー名 (color_name カラム)
    • 背景色を lucky_color のカラーコードにする
解答例 z-show.php
<?php
require 'common.php';

$sign_id = $_GET['id'] ?? 0;

// 選択された星座を取得
$sql = $pdo->prepare('SELECT * FROM zodiac WHERE id=?');
$sql->execute([$sign_id]);
$row = $sql->fetch(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title><?= $row ? h($row['sign']) . ' の運勢' : '星占い結果'; ?></title>
    <style>
        body {
            background-color: <?= $row ? h($row['lucky_color']) : '#fff'; ?>;
        }
        .lucky_color {
            color: <?= $row ? h($row['lucky_color']) : '#000'; ?>;
        }
    </style>
    <link rel="stylesheet" href="style.css">
</head>

<body>

<?php if ($row): ?>
    <div class="card">
        <!-- 画像 -->
        <img src="img/<?= h($row['image']) ?>" alt="<?= h($row['sign']) ?>">

        <!-- 星座名 -->
        <h2><?= h($row['sign']) ?> の運勢</h2>

        <!-- 運勢とラッキーカラー -->
        <p><?= nl2br(h($row['fortune'])) ?></p>
        <p>ラッキーカラー:<span class="lucky_color"><?= h($row['color_name']) ?></span></p>

        <p><a href="z-list.php">← 一覧に戻る</a></p>
    </div>
<?php else: ?>
    <div class="card">
        <p>選択された星座が見つかりません。</p>
        <p><a href="z-list.php">一覧に戻る</a></p>
    </div>
<?php endif; ?>

</body>
</html>

スコアを元にランキングも表示しよう!

ランキング(順位)を計算

z-list.phpファイルに下記のコードを追加してみましょう

<?php
require 'common.php';

$sign_id = $_GET['id'] ?? 0;

// まず選択された星座を取得
$sql = $pdo->prepare('SELECT * FROM zodiac WHERE id=?');
$sql->execute([$sign_id]);
$row = $sql->fetch(PDO::FETCH_ASSOC);

// 順位計算(scoreでソートして、何位かを求める)
$rank = null;
if ($row) {
    //zodiac_score テーブルから id カラムだけを、score の降順で取得。
    //スコアの高い順に並べた星座IDの一覧の取得。
    $sql_all = $pdo->query('SELECT id FROM zodiac ORDER BY score DESC');

    //連想配列の配列
    //     $all = [
    //     0 => ['id' => 3],  // スコア1位の星座(id=3)
    //     1 => ['id' => 7],  // スコア2位の星座(id=7)
    //     2 => ['id' => 1],  // スコア3位の星座(id=1)
    //     ...
    // ];
    $all = $sql_all->fetchAll(PDO::FETCH_ASSOC);

    //foreach で1行ずつ見ていき、「選ばれた星座のidと一致する行」を探す
    foreach ($all as $index => $r) {
        //$r['id'] は「今ループで取り出した行のid」
        //$sign_id は「URLパラメータで指定されたid(選ばれた星座のid)」
        if ($r['id'] === $sign_id) {
            $rank = $index + 1; // 配列は0始まりなので+1
        }
    }
}
?>
解答例 z-ranking.php
<?php
require 'common.php';

$sign_id = $_GET['id'] ?? 0;

// まず選択された星座を取得
$sql = $pdo->prepare('SELECT * FROM zodiac WHERE id=?');
$sql->execute([$sign_id]);
$row = $sql->fetch(PDO::FETCH_ASSOC);

// 順位計算(scoreでソートして、何位かを求める)
$rank = null;
if ($row) {
    //zodiac_score テーブルから id カラムだけを、score の降順で取得。
    //スコアの高い順に並べた星座IDの一覧の取得。
    $sql_all = $pdo->query('SELECT id FROM zodiac ORDER BY score DESC');

    //連想配列の配列
    //     $all = [
    //     0 => ['id' => 3],  // スコア1位の星座(id=3)
    //     1 => ['id' => 7],  // スコア2位の星座(id=7)
    //     2 => ['id' => 1],  // スコア3位の星座(id=1)
    //     ...
    // ];
    $all = $sql_all->fetchAll(PDO::FETCH_ASSOC);

    //foreach で1行ずつ見ていき、「選ばれた星座のidと一致する行」を探す
    foreach ($all as $index => $r) {
        //$r['id'] は「今ループで取り出した行のid」
        //$sign_id は「URLパラメータで指定されたid(選ばれた星座のid)」
        if ($r['id'] == $sign_id) {
            $rank = $index + 1; // 配列は0始まりなので+1
        }
    }
}
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title><?= $row ? h($row['sign']) . ' の運勢' : '星占い結果'; ?></title>
    <style>
        body {
            background-color: <?= $row ? h($row['lucky_color']) : '#fff'; ?>;
        }

        .lucky_color {
            color: <?= $row ? h($row['lucky_color']) : '#000'; ?>;
        }
    </style>
    <link rel="stylesheet" href="style.css">
</head>

<body>

    <?php if ($row): ?>
        <div class="card">
            <!-- 画像 -->
            <img src="img/<?= h($row['image']) ?>" alt="<?= h($row['sign']) ?>">

            <!-- 星座名と順位 -->
            <h2><?= h($row['sign']) ?> の運勢</h2>
            <?php if ($rank): ?>
                <p><strong>今月の順位:<?= h($rank) ?>位</strong></p>
            <?php endif; ?>

            <!-- 運勢とラッキーカラー -->
            <p><?= nl2br(h($row['fortune'])) ?></p>
            <p>
                ラッキーカラー:<span class="lucky_color"><?= h($row['color_name']) ?></span>
            </p>

            <p><a href="z-list.php">← 一覧に戻る</a></p>
        </div>
    <?php else: ?>
        <div class="card">
            <p>選択された星座が見つかりません。</p>
            <p><a href="z-list.php">一覧に戻る</a></p>
        </div>
    <?php endif; ?>

</body>

</html>

ステップアップ:z-list.php をランキング順に並べる

一覧ページを id順(12星座の固定順) ではなく、score(スコアの降順) で並べ替えてランキング表示にしてみましょう。

  1. SQLの並び順を変更する
    • これまで ORDER BY id だった部分を
      ORDER BY score DESC に変更します。
    • DESC は「降順」という意味で、大きい数字から順に並べます。
  2. スコアも取得して表示する
    • SELECT id, sign, image, score FROM zodiac として、scoreカラムも取り出します。
    • HTML部分で <?= $s['score'] ?>点 を追加すると、点数付きで表示できます。
  3. ランキング形式で表示する
    • <ul> ではなく <ol>(順序付きリスト)を使うとマークアップになります。
    • 各行には「スコア」「星座名」「詳細リンク」を表示します。
  4. 1位だけclassをつけて目立つように表示
解答例 z-list-ranking.php
<?php
require 'common.php';
// スコアの高い順に並べ替え
$sql = $pdo->query('SELECT id, sign, image, score FROM zodiac ORDER BY score DESC');
$signs = $sql->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>星座ランキング</title>
    <style>
        .first {
            font-size: 1.5em;
            font-weight: bold;
            color: red;
            background: #ffe600;
            padding: 5px 10px;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <h1>星座ランキング</h1>
    <ol>
        <?php foreach ($signs as $index => $s): ?>
            <li class="<?= ($index === 0) ? 'first' : '' ?>">
                <?= ($index + 1) ?>位 
                <?= $s['score'] ?>点 
                <a href="z-show.php?id=<?= $s['id'] ?>">
                    <?= htmlspecialchars($s['sign']) ?>
                </a>
            </li>
        <?php endforeach; ?>
    </ol>
</body>
</html>