PHP + MySQLによる簡単なブログサイトの構築

カテゴリ:PHP編

MySQLと連携してブログを作成する場合、WordPressのようなCMS、LaravelやCakePHPのようなPHPフレームワークを利用するのが一般的です。しかし個人ブログであれば、学習も兼ねて1からブログサイトを構築するのも一興です。 単に楽しいだけではなく、セキュリティ面なども含めてすべて自分でテスト、管理しなければならずなかなか大変ですが、完全オリジナルであるため細かいところまで一切の制約なく自由にカスタマイズできる利点は非常に大きいです。

このページでは、1からブログサイトを開発する際の、特にコアとなるPHPとMySQLとの連携部分に焦点を当てて解説していきたいと思います。

NoteあくまでもPHPとMySQLとの基礎的な連携方法を解説したものであり、デザインやユーザビリティ、バリデーション等は考慮していないためご了承ください。

データベース構成

サンプルデータベースは、PHPでのデータベースプログラミングに引き続きblogデータベース(blogとcategory_listの2つのテーブルから成る)を使用する事にします。

ブログの登録ページの作成

ブログの登録フォームには、カテゴリー(category)、タイトル(title)、本文(text)の3つの入力項目が必要です。 そのため、以下のようなフォームを作成します。

ファイル名:article_add.php

HTML部分:

<!-- 記事の登録フォーム -->
<form name="artible_add" action="article_add.php" method="post">
    <p>カテゴリ:<input name="category" type="text">
    <p>タイトル:<input name="title" type="text">
    <p>本文:<br><textarea name="text" cols="50" rows="10"></textarea>
    <p><input type="submit" value="登録">
</form>

次に、データベースに記事を登録するPHPのコードは以下のようになります。SQLクエリの処理は、入力されたカテゴリーがcategory_listテーブルに存在するかを確認し、存在しなければ新規カテゴリーとして追加する部分と、blogテーブルに記事を登録する部分との2つに分けられます。

Noteblogテーブルにはカテゴリーをcategory_listテーブルへの副問合せを用いてcategory_idで登録しています。

PHP部分:

//title、text、cateoryパラメータがPOSTメソッドで送られてきたら登録と判断
if (isset ($_POST['title']) && isset ($_POST['text']) && isset ($_POST['category']) ) {
    $title = $_POST['title'];
    $text = $_POST['text'];
    $category = $_POST['category'];

    //実際にはここで入力値の検証を実施

    //データベース接続
    $dsn = "mysql:host=localhost;dbname=blog";
    $username = "root";
    $password = "pass";
    $db = new PDO($dsn, $username, $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //category_listテーブルに同名のカテゴリーが存在しなければカテゴリーを登録
    try {
        $res = $db->query("SELECT COUNT(*) FROM category_list WHERE category = '" . $category . "'");
        if ($res->fetchColumn() == 0) {
            $statement = $db->prepare("INSERT INTO category_list (category) VALUES (:category)");
            $statement->bindValue(':category', $category, PDO::PARAM_STR);
            $statement->execute();
            $statement = null;
            echo "カテゴリーを追加しました。";
        }
    }
    catch (Exception $error) {
        echo "カテゴリーの登録失敗:" . $error->getMessage();
    }

    //記事を登録
    try {
        $statement = $db->prepare("INSERT INTO blog (title, text, date, category_id) VALUES (:title, :text, NOW(), (SELECT id FROM category_list WHERE category = :category))");
        $statement->bindValue(':title', $title, PDO::PARAM_STR);
        $statement->bindValue(':text', $text, PDO::PARAM_STR);
        $statement->bindValue(':category', $category, PDO::PARAM_STR);
        $statement->execute();
        $statement = null;
        echo "記事を追加しました。";
        }
    catch (Exception $error) {
        echo "記事の登録失敗:" . $error->getMessage();
    }
}

Noteここでは入力値の検証(データバリデーション)は省略していますが、PHPによる入力データの検証(データバリデーション)でバリデーションクラスの作成と実装方法を解説しています。

ブログの閲覧ページの作成

次にブログの記事を表示するためのページを作成していきます。つまり訪問ユーザーが記事を閲覧するページです。表示のみであるためSQL文はSELECT文のみを使用します。

ファイル名:article.php

PHP部分:

//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);

//全記事を抽出
$statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog ORDER BY date DESC");
$statement->execute();


//記事をHTMLに出力
while ($row = $statement->fetch()) {
    echo "<article>";
    echo "<h1>" . $row['title'] . "</h1>";
    echo "<p>カテゴリー:" . $row['category'];
    echo "<p>" . $row['text'];
    echo "<p>投稿日時:" . $row['date'];
    echo "</article>";
}

$statement = null;

参考記事ページは、実際には記事IDをパラメータとして渡し、特定IDの記事のみを表示するページを作成しましょう。

ブログの更新ページの作成

記事の更新ページは登録ページと共通点も多いですが、対象記事IDの登録済みデータをフォームに表示する点と、編集対象の記事IDをキーとしてデータベースにUPDATE文を実行する点が異なります。

Note渡されたパラメータのメソッドの種類(GET、POST)やパラメータ数に応じて、フォームへの表示リクエストか、テーブルデータの更新リクエストかを判別する方法を取っています。

ファイル名:article_modify.php

PHP部分:

//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//idパラメータがGETメソッドで送られてきたら、該当idの記事データを取得してフォームに表示
if (isset ($_GET['id'])) {
    $id = $_GET['id'];
    $statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog WHERE id = :id");
    $statement->bindValue(':id', $id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetch();
}

HTML部分:

<!-- 記事の更新フォーム -->
<form name="article_modify" action="article_modify.php" method="post">
    <p>記事ID:<?php echo $row['id']; ?>
    <p>カテゴリ:<input name="category" type="text" value="<?php echo $row['category']; ?>">
    <p>タイトル:<input name="title" type="text" value="<?php echo $row['title']; ?>">
    <p>本文:<br><textarea name="text" cols="50" rows="10"><?php echo $row['text']; ?></textarea>
    <input name="id" type="hidden" value="<?php echo $row['id']; ?>">
    <p><input type="submit" value="更新">
</form>

次に、データベースの記事を更新する場合のPHPのコードは以下のようになります。POSTメソッドでid、title、text、cateoryの4つのパラメータが指定されている場合に記事の更新リクエストであると判断します。

PHP部分:

//id、title、text、cateoryパラメータがPOSTメソッドで送られてきたら更新と判断
if (isset ($_POST['id']) && isset ($_POST['title']) && isset ($_POST['text']) && isset ($_POST['category'])) {
    $id = $_POST['id'];
    $title = $_POST['title'];
    $text = $_POST['text'];
    $category = $_POST['category'];

    //実際にはここで入力値の検証を実施

    //category_listテーブルに同名のカテゴリーが存在しなければカテゴリーを登録
    try {
        $res = $db->query("SELECT COUNT(*) FROM category_list WHERE category = '" . $category . "'");
        if ($res->fetchColumn() == 0) {
            $statement = $db->prepare("INSERT INTO category_list (category) VALUES (:category)");
            $statement->bindValue(':category', $category, PDO::PARAM_STR);
            $statement->execute();
            $statement = null;
            echo "カテゴリーを追加しました。";
        }
    }
    catch (Exception $error) {
        echo "カテゴリーの登録失敗:" . $error->getMessage();
    }

    //記事を更新
    try {
        $statement = $db->prepare("UPDATE blog SET title = :title, text = :text, category_id = (SELECT id FROM category_list WHERE category = :category) WHERE id = :id");
        $statement->bindValue(':title', $title, PDO::PARAM_STR);
        $statement->bindValue(':text', $text, PDO::PARAM_STR);
        $statement->bindValue(':category', $category, PDO::PARAM_STR);
        $statement->bindValue(':id', $id, PDO::PARAM_INT);
        $statement->execute();
        $statement = null;
        echo "記事を更新しました。";
        }
    catch (Exception $error) {
        echo "記事の更新失敗:" . $error->getMessage();
    }
}

パラメータにid=1を付与して記事ID 1の記事の更新ページを表示し、実際に内容が更新できるかを確認してみましょう。

http://localhost/article_modify.php?id=1

参考後述するように、実際には各記事へのパラメータ付きリンクを設置した記事一覧ページを作成し、記事の編集ページに移動できるように構成します。

記事一覧ページの作成

最後に編集記事一覧ページを作成してみます。記事一覧はSELECT文を用い、前記事のid、category、title、dateを取得し、while文を用いて1記事ごとにテーブル形式で一覧として表示します。

また、タイトル欄は記事更新ページ(article_modify.php)にidパラメータを付与したハイパーリンクとして作成しています。

ファイル名:article_list.php

//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//全記事を抽出
$statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, date FROM blog ORDER BY date DESC");
$statement->execute();

//記事一覧をHTMLに出力
echo "<table>";
echo "<tr><th>記事ID</th><th>カテゴリー</th><th>タイトル</th><th>投稿日時</th></tr>";
while ($row = $statement->fetch()) {
    echo "<tr>";
    echo "<td>" . $row['id'] . "</td>";
    echo "<td>" . $row['category'] . "</td>";
    echo "<td><a href=\"article_modify.php?id=" . $row['id'] . "\">" . $row['title'] . "</a></td>";
    echo "<td>" . $row['date'] . "</td>";
    echo "</tr>";
}
echo "</table>";

$statement = null;

参考実際にはページ送りを設置して1ページあたり10~50記事程度のリンクに分割したり、カテゴリーで抽出できる機能を追加すると、目的の記事を探しやすくなるでしょう。

まとめ

最終的に作成した4つのPHPファイルは以下となります。

なお、記事の登録ページと編集ページは1つのリクエストでフォームの表示かデータの登録・更新処理のどちらか一方しか処理しないため、if else 文で処理を分岐させています。

ブログ記事の登録ページ(article_add.php)

<html>
<?php
//title、text、cateoryパラメータがPOSTメソッドで送られてきたら登録と判断
if (isset ($_POST['title']) && isset ($_POST['text']) && isset ($_POST['category']) ) {
    $title = $_POST['title'];
    $text = $_POST['text'];
    $category = $_POST['category'];

    //実際にはここで入力値の検証を実施

    //データベース接続
    $dsn = "mysql:host=localhost;dbname=blog";
    $username = "root";
    $password = "pass";
    $db = new PDO($dsn, $username, $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //category_listテーブルに同名のカテゴリーが存在しなければカテゴリーを登録
    try {
        $res = $db->query("SELECT COUNT(*) FROM category_list WHERE category = '" . $category . "'");
        if ($res->fetchColumn() == 0) {
            $statement = $db->prepare("INSERT INTO category_list (category) VALUES (:category)");
            $statement->bindValue(':category', $category, PDO::PARAM_STR);
            $statement->execute();
            $statement = null;
            echo "カテゴリーを追加しました。";
        }
    }
    catch (Exception $error) {
        echo "カテゴリーの登録失敗:" . $error->getMessage();
    }

    //記事を登録
    try {
        $statement = $db->prepare("INSERT INTO blog (title, text, date, category_id) VALUES (:title, :text, NOW(), (SELECT id FROM category_list WHERE category = :category))");
        $statement->bindValue(':title', $title, PDO::PARAM_STR);
        $statement->bindValue(':text', $text, PDO::PARAM_STR);
        $statement->bindValue(':category', $category, PDO::PARAM_STR);
        $statement->execute();
        $statement = null;
        echo "記事を追加しました。";
        }
    catch (Exception $error) {
        echo "記事の登録失敗:" . $error->getMessage();
    }
} else { ?>
    <!-- 記事の登録フォーム -->
    <form name="artible_add" action="article_add.php" method="post">
        <p>カテゴリ:<input name="category" type="text">
        <p>タイトル:<input name="title" type="text">
        <p>本文:<br><textarea name="text" cols="50" rows="10"></textarea>
        <p><input type="submit" value="登録">
    </form>
<?php } ?>
</html>

ブログ記事の閲覧ページ(article.php)

<html>
<?php
//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);

//全記事を抽出
$statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog ORDER BY date DESC");
$statement->execute();


//記事をHTMLに出力
while ($row = $statement->fetch()) {
    echo "<article>";
    echo "<h1>" . $row['title'] . "</h1>";
    echo "<p>カテゴリー:" . $row['category'];
    echo "<p>" . $row['text'];
    echo "<p>投稿日時:" . $row['date'];
    echo "</article>";
}

$statement = null;
?>
</html>

ブログ記事の更新ページ(article_modify.php)

<html>
<?php
//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//id、title、text、cateoryパラメータがPOSTメソッドで送られてきたら更新と判断
if (isset ($_POST['id']) && isset ($_POST['title']) && isset ($_POST['text']) && isset ($_POST['category'])) {
    $id = $_POST['id'];
    $title = $_POST['title'];
    $text = $_POST['text'];
    $category = $_POST['category'];

    //実際にはここで入力値の検証を実施

    //category_listテーブルに同名のカテゴリーが存在しなければカテゴリーを登録
    try {
        $res = $db->query("SELECT COUNT(*) FROM category_list WHERE category = '" . $category . "'");
        if ($res->fetchColumn() == 0) {
            $statement = $db->prepare("INSERT INTO category_list (category) VALUES (:category)");
            $statement->bindValue(':category', $category, PDO::PARAM_STR);
            $statement->execute();
            $statement = null;
            echo "カテゴリーを追加しました。";
        }
    }
    catch (Exception $error) {
        echo "カテゴリーの登録失敗:" . $error->getMessage();
    }

    //記事を更新
    try {
        $statement = $db->prepare("UPDATE blog SET title = :title, text = :text, category_id = (SELECT id FROM category_list WHERE category = :category) WHERE id = :id");
        $statement->bindValue(':title', $title, PDO::PARAM_STR);
        $statement->bindValue(':text', $text, PDO::PARAM_STR);
        $statement->bindValue(':category', $category, PDO::PARAM_STR);
        $statement->bindValue(':id', $id, PDO::PARAM_INT);
        $statement->execute();
        $statement = null;
        echo "記事を更新しました。";
        }
    catch (Exception $error) {
        echo "記事の更新失敗:" . $error->getMessage();
    }
} else //idパラメータがGETメソッドで送られてきたら、該当idの記事データを取得してフォームに表示
if (isset ($_GET['id'])) {
    $id = $_GET['id'];
    $statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog WHERE id = :id");
    $statement->bindValue(':id', $id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetch();
?>
<!-- 記事の更新フォーム -->
<form name="article_modify" action="article_modify.php" method="post">
    <p>記事ID:<?php echo $row['id']; ?>
    <p>カテゴリ:<input name="category" type="text" value="<?php echo $row['category']; ?>">
    <p>タイトル:<input name="title" type="text" value="<?php echo $row['title']; ?>">
    <p>本文:<br><textarea name="text" cols="50" rows="10"><?php echo $row['text']; ?></textarea>
    <input name="id" type="hidden" value="<?php echo $row['id']; ?>">
    <p><input type="submit" value="更新">
</form>
<?php } ?>
</html>

ブログの記事一覧ページ(article_list.php)

<html>
<?php
//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//全記事を抽出
$statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, date FROM blog ORDER BY date DESC");
$statement->execute();

//記事一覧をHTMLに出力
echo "<table>";
echo "<tr><th>記事ID</th><th>カテゴリー</th><th>タイトル</th><th>投稿日時</th></tr>";
while ($row = $statement->fetch()) {
    echo "<tr>";
    echo "<td>" . $row['id'] . "</td>";
    echo "<td>" . $row['category'] . "</td>";
    echo "<td><a href=\"article_modify.php?id=" . $row['id'] . "\">" . $row['title'] . "</a></td>";
    echo "<td>" . $row['date'] . "</td>";
    echo "</tr>";
}
echo "</table>";

$statement = null;
?>
</html>

以上、PHP+MySQLによる簡単なブログサイトの構築の解説でした。

公開日時:2020年06月07日 23:01:46
最終更新日時:2022年02月17日 15:57:48

なお、レンタルサーバー選びで迷ったらこちらの記事で主要レンタルサーバーのプランと料金を比較していますので、是非参考にしてみてください。

PHP編に戻る

このページのトップに戻る