記事詳細画面

記事だけのコンテンツであれば、今までの実装で、「一覧、作成、編集、削除」機能が備わっています。
しかし、今回はコメント機能もつけたいと思うので、記事の詳細ページを作りましょう。
その詳細ページでコメントできるものとします。

メインページの改修


さて、記事編集画面、削除機能でやったように、メインページに詳細ページへのリンクを作成しましょう。
例のごとく、左に+マークがついた行を追記してください。

<table>
    <tr>
        <td>記事ID</td>
        <td>タイトル</td>
        <td>本文</td>
        <td>投稿日</td>
+       <td></td>
        <td></td>
        <td></td>
    </tr>
    <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { ?>
        <tr>
            <td><?php echo $row['id']; ?></td>
            <td><?php echo $row['title']; ?></td>
            <td><?php echo $row['content']; ?></td>
            <td><?php echo $row['time']; ?></td>
+           <td><a href="detail_post.php?id=<?php echo $row['id']; ?>">詳細</a></td>
            <td><a href="edit_post.php?id=<?php echo $row['id']; ?>">編集</a></td>
            <td><a href="delete_post.php?id=<?php echo $row['id']; ?>">削除</a></td>
        </tr>
    <?php } ?>
</table>

詳細ページのファイル名はdetail_post.phpとします。
そのページでは対象記事IDを表示させたいので、GETでidを渡します。

<a href="detail_post.php?id=<?php echo $row['id']; ?>">詳細</a>

記事詳細ページの実装


記事詳細ページの実装ですが、記事編集画面、削除機能の編集画面とPHP部分は同様です。
そのため、ヒントのサンプルコードを記載します。

後々のため、コメントを新規作成できるリンクだけつけておきます。
GETでpost_idを渡していますが、この説明は次項でします。

<a href="create_comment.php?post_id=<?php echo $id ?>">この記事にコメントする</a>

サンプル

detail_post.php

リファクタリング


さて、ここでこんなことを思った方がいるかもしれません。

あれ、同じようなコードを書いているから一まとめにできないかな?

それは非常に感性が良いと思います。
正直、記事編集画面と詳細画面はPHPで似たようなコードが多いです。
ここをfunction.phpで関数にしてしまいましょう。

このように、コードを再整備することを リファクタリング といいます。

$idが空だったらメインページにリダイレクトさせる


このコードはedit_post.phpdetail_post.phpの両方に存在します。

// もし、$idが空であったらmain.phpにリダイレクト
// 不正なアクセス対策
if (empty($id)) {
    header("Location: main.php");
    exit;
}

これは関数にできそうです。
そのため、function.phpに追加しましょう!
関数名はredirect_main_unless_parameterとします。

/**
 * 引数の値が空だった場合、main.phpにリダイレクトする
 * @param integer $param
 * @return void
 */
function redirect_main_unless_parameter($param) {
    if (empty($param)) {
        header("Location: main.php");
        exit;
    }
}

引数名を$paramとすることで、$idだけでなく他の要素で使用しても違和感がないです。

さて、この関数が用意できたので、edit_post.phpdetail_post.phpを書き換えましょう。
左端に-が付いているコードは消してください。
左端に+が付いているコードは代わりに追加してください。

-   // もし、$idが空であったらmain.phpにリダイレクト
-   // 不正なアクセス対策
-   if (empty($id)) {
-        header("Location: main.php");
-        exit;
-   }

+   redirect_main_unless_parameter($id);

1行になってスッキリしましたね。

postsテーブルから1件取得する部分


正直、下記のコードも全く同じです。

try {
    // PDOのインスタンスを生成
    $pdo = db_connect();
    // SQL文の準備
    $sql = "SELECT * FROM posts WHERE id = :id";
    // プリペアドステートメントの作成
    $stmt = $pdo->prepare($sql);
    // idのバインド
    $stmt->bindParam('id', $id);
    $stmt->execute();
} catch (PDOException $e) {
    // エラーメッセージの出力
    echo 'Error: ' . $e->getMessage();
    // 終了
    die();
}

// 結果が1行取得できたら
if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $id = $row['id'];
    $title = $row['title'];
    $content = $row['content'];
} else {
    // 対象のidでレコードがない => 不正な画面遷移
    echo "対象のデータがありません。";
}

さて、関数名はどうしましょうか。。。

今回はpostsテーブルからidで1件取得してくるので、find_post_by_idとしましょう。

/**
 * 引数で与えられたidでpostsテーブルを検索する
 * もし対象のレコードがなければmain.phpに遷移させる
 * @param integer $id
 * @return array
 */
function find_post_by_id($id) {
    // PDOのインスタンスを生成
    $pdo = db_connect();
    try {
        // SQL文の準備
        $sql = "SELECT * FROM posts WHERE id = :id";
        // プリペアドステートメントの作成
        $stmt = $pdo->prepare($sql);
        // idのバインド
        $stmt->bindParam('id', $id);
        // 実行
        $stmt->execute();
    } catch (PDOException $e) {
        // エラーメッセージの出力
        echo 'Error: ' . $e->getMessage();
        // 終了
        die();
    }
    // 結果が1行取得できたら
    if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        return $row;
    } else {
        redirect_main_unless_parameter($row);
    }
}

もし、結果が1行も取得できなかったら、わざわざ結果がないことを表示する必要はあるでしょうか?
その場合はメインページに戻してしまいましょう。

先ほど作成したredirect_main_unless_parameterが使えます!

さぁ、edit_post.phpdetail_post.phpを書き換えましょう。
なんと、try ~ catchの部分が下記の5行で済みます!(コメントがなければ4行)

$row = find_post_by_id($id);
// 関数から取得した値を格納
$id = $row['id'];
$title = $row['title'];
$content = $row['content'];

 

 

カテゴリー

アーカイブ

Close Bitnami banner
Bitnami