【PHP入門】プレーンなPHPでブログを作成する・その2【ルーティング&ビュー編】

前回

前回ブログを作成するにあたって環境構築を行った。今回はルーティングと見た目部分であるビューを作成する。

1.ルーティング

ルーティングを行うためにpublic/index.phpを作成する。public/index.phpは下記の通り。

<?php

$PATH = $_SERVER['PATH_INFO'];
if(empty($PATH)){
    $PATH = $_SERVER['REQUEST_URI'];
    $PATH = preg_replace('/^\//','',$PATH);
}

if(empty($PATH)){
    include("../views/index.php");
}else{
    include("../views/${PATH}.php");
}

PATH_INFOの値に応じてビューを読み込む簡単仕様。PATH_INFOが空のときにはREQUEST_URIをパースする。

2.ビュー

2-1.ブログ一覧

ブログ一覧を表示するindex.phpは下記の通り。

<?php
    include("../lib/login.php");
    session_start();
    header('Content-Type: text/html; charset=UTF-8');
?>
<header>
    <link href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css" rel="stylesheet"/>
</header>
<body>
    <div class="container">
        <h2 class="subtitle">ブログ一覧画面</h2>
        <?php 
            if(isset($_SESSION['username'])){
        ?>
        <nav class="level">
            <div class="level-left">
                <div class="level-item">
                    <a class="button is-small" href="/create">新規投稿</a>
                </div>
            </div>
            <div class="level-right">
                <div class="level-item">
                    <form action="logout" method="post">
                        <input type="hidden" name="token" value="<?= h(generate_token())?>"/>
                        <button class="button is-small" type="submit">ログアウト</button>
                    </form>
                </div>
            </div>
        </nav>
        <?php
            }else{
        ?>
            <a class="button is-small" href="/login">ログイン</a>
        <?php                
            }
        ?>
        <?php 
            include('../models/Blog.php');
            $blog = new Blog;
            $posts = $blog->read();
            foreach($posts as $post){ 
                if(!isset($_SESSION['username']) && boolval($post['private'])){
                   continue; 
                }
        ?>
        <form action="delete" method="post">
            <input type="hidden" name="id" value="<?php echo($post['id'])?>"/>
            <input type="hidden" name="title" value="<?php echo($post['title'])?>"/>
            <input type="hidden" name="content" value="<?php echo($post['content'])?>"/>
            <div class="box">
                <h2><?php echo($post['title']) ?></h2>
                <div><?= boolval($post['private']) ? "非公開" : "公開" ?></div>
                <article>
                    <?php echo($post['content']) ?>
                </article>
                <?php 
                    if(isset($_SESSION['username'])){
                ?>
                <button class="button is-danger is-small" type='submit'>投稿を削除する</button>
                <?php
                    }
                ?>
            </div>
        </form>
        <?php } ?>
    </div>
</body>

上段は後ほど作成する認証処理のための記述である。

データを読み込む部分について。

<?php 
            include('../models/Blog.php');
            $blog = new Blog;
            $posts = $blog->read();
            foreach($posts as $post){ 
                if(!isset($_SESSION['username']) && boolval($post['private'])){
                   continue; 
                }
        ?>

DBからデータを読み込む部分は後ほど作成するモデルに任せるので、ビューはモデルをインスタンス化してメソッドを読み出して、foreachで表示するのみ。ただし、認証済みユーザに対してのみ非公開の記事を表示するので、セッションが無効かつprivateフラグが有効な記事は表示しないように記述する。

2-2.ブログ投稿

続いてブログ投稿に関するcreate.phpは下記の通り。

<?php
    include("../lib/login.php");
    required_logined_session();

    if(!empty($_POST["title"]) && !empty($_POST["content"])){
        $value = [
            "title" => $_POST["title"],
            "content" => $_POST["content"],
            "private" => isset($_POST["private"]) ? $_POST['private'] : "0",
        ];
        include("../models/Blog.php");
        $blog = new Blog;
        $blog->create($value);

        header('Location: /',true,301);
        exit;
    }
?>
<header>
    <link href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css" rel="stylesheet"/>
</header>
<body>
    <div class="container">
        <h2 class="subtitle">新規投稿画面</h2>
        <form action="" method="post">
            <div class="field">
                <div class="control">
                    <label class="label">タイトル</label>
                    <input class="input" name="title" type="text"/>
                </div>
            </div>
            <div class="field">
                <div class="control">
                    <label class="label">本文</label>
                    <textarea class="textarea" name="content"></textarea>
                </div>
            </div>
            <div>
                <label class="checkbox">
                    <input type="checkbox" name="private" value="1"/>
                    非公開にする
                </label>
            </div>
            <button class="button" type="submit">投稿する</button>
        </form>
    </div>
</body>

ブログ投稿部分は下記の通り。

if(!empty($_POST["title"]) && !empty($_POST["content"])){
        $value = [
            "title" => $_POST["title"],
            "content" => $_POST["content"],
            "private" => isset($_POST["private"]) ? $_POST['private'] : "0",
        ];
        include("../models/Blog.php");
        $blog = new Blog;
        $blog->create($value);

        header('Location: /',true,301);
        exit;
    }

$_POSTに入っている値をBlogモデルに渡して、/にリダイレクトする。

2-3.ブログ削除

delete.phpは下記の通り。

<?php
include('../models/Blog.php');

$blog = new Blog;
$blog->delete($_POST['id']);

header('Location: /',true,301);

2-4.ユーザ登録

register.phpは下記の通り。

<?php
    if(!empty($_POST["username"]) && !empty($_POST["password"])){
        $value = [
            "username" => $_POST["username"],
            "password" => $_POST["password"],
        ];
        include("../models/User.php");
        $blog = new User;
        $blog->create($value);

        header('Location: /',true,301);
        exit;
    }
?>
<header>
    <link href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css" rel="stylesheet"/>
</header>
<body>
    <div class="container">
        <h2 class="subtitle">ユーザー登録画面</h2>
        <form action="" method="post">
            <div class="field">
                <div class="control">
                    <label class="label">ユーザ名</label>
                    <input class="input" name="username" type="text"/>
                </div>
            </div>
            <div class="field">
                <div class="control">
                    <label class="label">パスワード</label>
                    <input class="input" name="password" type="password"/>
                </div>
            </div>
            <div class="field">
                <div class="control">
                    <label class="label">パスワード(確認用)</label>
                    <input class="input" type="password"/>
                </div>
            </div>
            <button class="button" type="submit">作成</button>
        </form>
    </div>
</body>

入力をユーザモデルに渡してリダイレクトする。

2-5.ログイン

login.phpは下記の通り。

<?php
    include("../lib/login.php");
    include("../models/User.php");
    required_unlogined_session();

    $user = new User;
    $username = filter_input(INPUT_POST,'username');
    $password = filter_input(INPUT_POST,'password');
    if($_SERVER['REQUEST_METHOD']==='POST'){
        if(
            $user->validate_password($username,$password)
        ){
            session_regenerate_id(true);
            $_SESSION['username'] = $username;
            header('Location: /');
            exit;
        }
        http_response_code(403);
    }
    header('Content-Type: text/html; charset=UTF-8');
?>
<header>
    <link href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css" rel="stylesheet"/>
</header>
<body>
    <div class="container">
        <h2 class="subtitle">ログイン画面</h2>
        <form action="" method="post">
            <div class="field">
                <div class="control">
                    <label class="label">ユーザ名</label>
                    <input class="input" name="username" type="text"/>
                </div>
            </div>
            <div class="field">
                <div class="control">
                    <label class="label">パスワード</label>
                    <input class="input" name="password" type="password"/>
                </div>
            </div>
            <input type="hidden" name="token" value="<?= h(generate_token())?>"/>
            <button class="button" type="submit">ログイン</button>
        </form>
    </div>
</body>

ユーザモデルのvaidate_password()でパスワードチェックをし、通ったらセッションIDをregenerateする。

2-6.ログアウト

logout.phpは下記の通り。

<?php
include('../lib/login.php');

required_logined_session();
if(!validate_token(filter_input(INPUT_POST,'token'))){
    header('Content-Type: text/plain; charset=UTF-8', true, 400);
    exit('トークンが無効です。');
}
setcookie(session_name(),'',1);
session_destroy();
header('Location: /');

validate_token()でトークンをチェックし、無効なトークンの場合は400を返す。

有効なトークンの場合はcookieを削除し、セッションをdestroyしてルートを返す。

まとめ

今回はルーティングとビューを作成した。この辺りからゴリゴリソースを書いていくことになるので楽しい。次回はモデルやDB周りを実装して行こうと思う。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA