【独学】はじめてのWebプログラミング – 9.6 Webページ開発 2-⑥

ログイン機能の作成

ユーザーモデルの変更

users.phpを以下のように修正します。

htdocs/Twitter/Models/users.php

<?php

// 設定ファイルの読み込み
include_once '../config.php';

// ユーザー登録関数
function createUser($data)
{
    // データベースに接続
    $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

    // 成功/失敗確認
    if ($mysqli->connect_errno) {
        echo 'MySQLの接続に失敗しました。<br>';
        exit;
    }

    // ユーザー登録のSQLを作成
    $query = 'INSERT INTO users (email, name, nickname, password) VALUES (?, ?, ?, ?)';

    // セキュリティ上、以下のように書く
    $statement = $mysqli->prepare($query);
    $statement->bind_param('ssss', $data['email'], $data['name'], $data['nickname'], $data['password']);

    // SQLを実行
    $response = $statement->execute();

    // 成功/失敗確認
    if ($response == false) {
        echo 'エラーが発生しました。<br>';
    }

    // データベースへの接続解除
    $statement->close();
    $mysqli->close();

    // result変数には、true(成功)or false(失敗)が入っている
    return $response;
}

// ★変更箇所(ここから)
// ログイン関数
function login($email, $password)
{
    // データベースに接続
    $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

    // 成功/失敗確認
    if ($mysqli->connect_errno) {
        echo 'MySQLの接続に失敗しました。<br>';
        exit;
    }

    // ユーザー情報取得のSQLを作成
    $query = 'SELECT * FROM users WHERE email = "'.$email.'"';

    // SQLを実行
    $result = $mysqli->query($query);

    // 成功/失敗確認
    if ($result == false) {
        echo 'エラーが発生しました。<br>';
        $mysqli->close();  // データベースへの接続解除
        return false;
    }

    // ユーザー情報を取得
    $user = $result->fetch_array(MYSQLI_ASSOC);
    if ($user == false) {
        echo 'ユーザーが存在しません。<br>';
        $mysqli->close();  // データベースへの接続解除
        return false;
    }

    // パスワードチェック
    if ($password != $user['password']) {
        echo 'パスワードが一致しません。<br>';
        $mysqli->close();  // データベースへの接続解除
        return false;
    }

    // データベースへの接続解除
    $mysqli->close();

    // ユーザー情報を返す
    return $user;
}
// ★変更箇所(ここまで)

?>

login関数を追加しています。
はじめに、データベースに接続をします。

次に、ユーザー情報を取得するSQL文字列を作成しています。文字列を結合しており、結合後のSQLは「SELECT * FROM users WHERE email = “入力されたメールアドレス”」になります。

次に、「$mysqli->query($query)」でSQLを実行しています。
query関数は、mysqliクラスの関数です。

次に、SQLの実行結果を確認しています。成功であれば変数$resultにはSQLの実行結果が入っており、失敗であればfalseが入っています。失敗の場合、データベースへの接続を解除した上で、login関数を抜けています。

次に、「$result->fetch_array(MYSQLI_ASSOC)」でSQLの実行結果を、連想配列として取得して変数$userに入れています。fetch_array関数はPHPの関数、MYSQLI_ASSOCはPHPの変数です。
$user[‘カラム名’]とすると、当該カラムの値が取得できるようになります。
fetch_array関数が失敗すると、変数$userにはfalseが入ります。失敗の場合、データベースへの接続を解除した上で、login関数を抜けています。

次に、 パスワードチェックをしています。ユーザーが入力したパスワード($password)と、データベースから取得したパスワード($user[‘password’])を比較しています。一致しなければ、データベースへの接続を解除した上で、login関数を抜けています。

パスワードチェックが通ればログインは成功です。
あとはデータベースへの接続を解除し、ユーザー情報を返しています。
(ログインに成功した場合はlogin関数の呼び出し元にはユーザー情報が返り、失敗した場合はfalseが返る、ということですね)

ログインコントローラーの変更

ログインコントローラーで、login関数を呼び出すようにします。

htdocs/Twitter/Controllers/sign-in.php

<?php

// ★変更箇所(ここから)
// ユーザーモデルを読み込み
include_once '../Models/users.php';

if (isset($_POST['email']) && isset($_POST['password'])) {
    // ログイン
    $user = login($_POST['email'], $_POST['password']);

    // ログインに成功した場合
    if ($user) {
        // 成功したらホーム画面に遷移
        header('Location: ../Controllers/home.php');
        exit;
    }
}
// ★変更箇所(ここまで)

// 画面表示
include_once '../Views/sign-in.php';

?>

はじめに、「include_once ‘../Models/users.php’」により、user.phpファイルを読み込んでいます(埋め込んでいます)。これにより、同ファイル内のlogin関数が使えるようになります。

次に、$_POST[‘email’]と$_POST[‘password’]がセットされているかを確認しており、セットされていれば{ … }内の処理が実行され、セットされていなければ再度ログイン画面(../Views/sign-in.php)が表示されることになります。

{ … }内では、login関数を呼び出し、成功した場合は「header(‘Location: ../Controllers/home.php’)」に遷移しています。失敗した場合は再度ログイン画面(../Views/sign-in.php)が表示されることになります。

ブラウザ

セッション管理

セッションを管理する関数の追加

Twitterフォルダ内に「util.php」ファイルを作成します。

VSCode

util.phpに以下の内容を書きます。

htdocs/Twitter/util.php

<?php

function saveSession($user)
{
    if (session_status() === PHP_SESSION_NONE) {
        // セッション開始
        session_start();
    }

    // セッションにユーザー情報を保存
    $_SESSION['USER'] = $user;
}

function deleteSession()
{
    if (session_status() === PHP_SESSION_NONE) {
        // セッション開始
        session_start();
    }

    // セッションのユーザー情報を削除
    unset($_SESSION['USER']);
}

function getSession()
{
    if (session_status() === PHP_SESSION_NONE) {
        // セッション開始
        session_start();
    }

    if (isset($_SESSION['USER']) == false) {
        // セッションにユーザー情報が存在しない
        return false;
    }

    // セッションのユーザー情報を返す
    $user = $_SESSION['USER'];
    return $user;
}

?>

セッション情報を保存する「saveSession関数」と、セッション情報を破棄する「deleteSession関数」を追加しました。

saveSession関数について解説します。
引数として、連想配列(ユーザー情報)を受け取るものとします。
session_statusはPHPの関数です。文字通りセッションの状態を取得することができます。PHP_SESSION_NONEはPHPの定数で、セッションが存在しない状態を示します。すなわち、セッションの状態を取得し、その状態がセッションが存在しない状態であれば、{ … }内の処理が行われます。
セッションが存在しない場合は、session_start関数により、セッションを開始します。
$_SESSIONはPHPの変数で、連想配列です。任意のキーを使って情報を登録することができます。ここでは、「USER」をキーとして、ユーザー情報を保存しています。

deleteSession関数について解説します。
セッション状態を確認してセッション開始する流れは上記と同じです。
unsetはPHPの関数で、引数で指定したデータを破棄してくれます。

getSession関数について解説します。
セッション状態を確認してセッション開始する流れは上記と同じです。
saveSession関数でセッション情報が保存されていれば、ユーザー情報である$_SESSION[‘USER’]は存在していますので、呼び出し元にそのユーザー情報を返します。保存されていなければ、呼び出し元にfalseを返しています。

ログインコントローラーの変更

ログインコントローラーで、saveSession関数を呼び出すようにします。

htdocs/Twitter/Controllers/sign-in.php

<?php

// ★変更箇所1(ここから)
include_once '../util.php';
// ★変更箇所1(ここまで)

// ユーザーモデルを読み込み
include_once '../Models/users.php';

if (isset($_POST['email']) && isset($_POST['password'])) {
    // ログイン
    $user = login($_POST['email'], $_POST['password']);

    // ログインに成功した場合
    if ($user) {
        // ★変更箇所2(ここから)
        // 成功したらユーザー情報をセッションに保存
        saveSession($user);
        // ★変更箇所2(ここまで)

        // 成功したらホーム画面に遷移
        header('Location: ../Controllers/home.php');
        exit;
    }
}

// 画面表示
include_once '../Views/sign-in.php';

?>

変更箇所1では、「include_once ‘../util.php’」により、util.phpファイルを読み込んでいます(埋め込んでいます)。これにより、同ファイル内のsaveSession関数が使えるようになります。

変更箇所2では、saveSession関数を呼び出しています。引数にはユーザー情報を指定しています。

ホームコントローラー

ホームコントローラーを以下のように修正します。

htdocs/Twitter/Controllers/home.php

<?php

// ★変更箇所1(ここから)
include_once '../util.php';

// ログインチェック
$view_user = getSession();
if ($view_user == false) {
    // ログインしていない
    header('Location: ../Controllers/sign-in.php');
    exit;
}
// ★変更箇所1(ここまで)

// ★変更箇所2(ここから)
// ツイート一覧
$view_tweets = [
    [
        'user_id' => 1,
        'user_name' => 'ichiro.suzuki',
        'user_nickname' => '鈴木一郎',
        'user_image_name' => 'sample.jpg',
        'tweet_body' => 'いまプログラミングをしています。',
        'tweet_image_name' => null,
        'tweet_created_at' => '2021-11-01 12:00:00',
        'like_id' => null,
        'like_count' => 0,
    ],
    [
        'user_id' => 2,
        'user_name' => 'jiro.suzuki',
        'user_nickname' => '鈴木二郎',
        'user_image_name' => 'sample2.jpg',
        'tweet_body' => '競馬場に来ました。',
        'tweet_image_name' => 'sample.jpg',
        'tweet_created_at' => '2021-11-02 09:00:00',
        'like_id' => 1,
        'like_count' => 1,
    ]
];
// ★変更箇所2(ここまで)

// 画面表示
include_once '../Views/home.php';

?>

変更箇所1では、「include_once ‘../util.php’」により、util.phpファイルを読み込んでいます(埋め込んでいます)。これにより、同ファイル内のgetSession関数が使えるようになります。
getSession関数を呼び出すことで、ログイン済みかをチェックしています。ログインしていればセッションにユーザー情報が保存されているため、ユーザー情報が取得できるのです。
仮にログインしていなければ(セッションのユーザー情報が取得できなければ)、「header(‘Location: ../Controllers/sign-in.php’)」によりログイン画面に遷移するようにしています。

変更箇所2について解説します。
このツイート一覧は、元々「Views/home.php」にありました。それを「Controllers/home.php」に移しただけです。

それに伴い、Views/home.phpを以下のように修正します。

htdocs/Twitter/Views/home.php

<!-- ★変更箇所(ここから)-->
<!-- ここに記載していたツイート一覧を削除 -->
<!-- ★変更箇所(ここまで)-->

<!DOCTYPE html>
<html>
    <lang="ja">
    <head>
        <?php include_once('../Views/common/header.php'); ?>
        <title>Twitter</title>
    </head>
    <body class="home">
        <div class="container">
            <?php include_once('../Views/common/side.php'); ?>
            <div class="main">
                <div class="main-header">
                    <h1>ホーム</h1>
                </div>
                <div class="tweet-post">
                    <div class="my-icon">
                        <img src="../Views/img_uploaded/user/sample.jpg" alt="">
                    </div>
                    <div class="input-area">
                        <form action="post.php" method="post" enctype="multipart/form-data">
                            <textarea name="body" placeholder="Hello" maxlength="140"></textarea>
                            <div class="bottom-area">
                                <div class="mb-0">
                                    <input type="file" name="image" class="form-control form-control-sm">
                                </div>
                                <button class="btn" type="submit">つぶやく</button>
                            </div>
                        </form>
                    </div>
                </div>
                <div class="ditch"></div>
                <?php if (empty($view_tweets)): ?>
                    <p class="p-3">ツイートがありません</p>
                <?php else: ?>
                    <div class="tweet-list">
                        <?php foreach ($view_tweets as $view_tweet) : ?>
                            <?php include('../Views/common/tweet.php'); ?>
                        <?php endforeach; ?>
                    </div>
                <?php endif; ?>
            </div>
        </div>
    </body>
</html>

ログアウト機能の作成

ログアウトコントローラーの作成

Controllersフォルダの中に「sign-out.php」ファイルを作成します。

VSCode

sign-out.phpに以下の内容を書きます。

htdocs/Twitter/Controllers/sign-out.php

<?php

include_once '../util.php';

// ユーザー情報をセッションから削除
deleteSession();

// ログイン画面に遷移
header('Location: ../Controllers/sign-in.php');
exit;

?>

はじめに、「include_once ‘../util.php’」により、util.phpファイルを読み込んでいます(埋め込んでいます)。これにより、同ファイル内のdeleteSession関数が使えるようになります。その上でdeleteSession関数を呼び出し、ユーザー情報をセッションから削除しています。

次に、「header(‘Location: ../Controllers/sign-in.php’)」により、ログイン画面に遷移しています。

サイド領域へのログアウト機能の追加

side.phpを以下のように修正します。

htdocs/Twitter/Views/common/side.php

<div class="side">
    <div class="side-inner">
        <ul class="nav flex-column">
            <li class="nav-item"><a href="home.php" class="nav-link"><img src="../Views/img/1.svg" alt="" class="icon"></a></li>
            <li class="nav-item"><a href="home.php" class="nav-link"><img src="../Views/img/2.svg" alt=""></a></li>
            <li class="nav-item"><a href="search.php" class="nav-link"><img src="../Views/img/3.svg" alt=""></a></li>
            <li class="nav-item"><a href="notification.php" class="nav-link"><img src="../Views/img/4.svg" alt=""></a></li>
            <li class="nav-item"><a href="profile.php" class="nav-link"><img src="../Views/img/5.svg" alt=""></a></li>
            <li class="nav-item"><a href="post.php" class="nav-link"><img src="../Views/img/6.svg" alt="" class="icon"></a></li>
            <li class="nav-item"><img src="../Views/img_uploaded/user/sample.jpg" alt="" class="my-icon"></li>
            <!-- ★変更箇所(ここから)-->
            <li><a href="sign-out.php" class="nav-link">logout</a></li>
            <!-- ★変更箇所(ここまで)-->
        </ul>
    </div>
</div>

aタグを使い、logoutを選択すると、「sign-out.php」へリンク(遷移)するようにしています。

ブラウザ

ここまで出来たら、変更内容をコミットし、GitHubにプッシュして下さい。

本節の説明は以上になります。

トップページ << [Windows] [Mac] 前のカリキュラムへ戻る 次のカリキュラムへ進む>>

タイトルとURLをコピーしました