LoginSignup
2
2

More than 3 years have passed since last update.

【PHPでECサイト②】ログイン機能

Last updated at Posted at 2020-08-07

はじめに

今回は、PHPとMySQLを使ってログイン機能を実装していきます。
※当ページは、【PHPでECサイト】で作られたものを前提にしています。

バージョン

PHP:7.4.5
phpMyAdmin:5.0.2
MySQL:5.7.30

今回作成するファイル

html
- login.php
- login_process.php
- signup.php
- signup_process.php
- logout.php

model
- users.php

view
- login_view.php
- signup_view.php

テーブルの作成

sample_users.sql
CREATE TABLE `sample_users` (
  `user_id` int(11) NOT NULL,
  `user_name` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL,
  `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `sample_users`
  MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT,
  ADD PRIMARY KEY (`user_id`);

定義

処理に使うものを追記

const.php
define('SIGNUP_URL', '/signup.php');
define('LOGIN_URL', '/login.php');
define('LOGOUT_URL', '/logout.php');

// 正規表現
define('REGEXP_ALPHANUMERIC', '/\A[0-9a-zA-Z]+\z/'); 

// 文字数制限
define('USER_NAME_LENGTH_MIN', 6);
define('USER_NAME_LENGTH_MAX', 20);
define('USER_PASSWORD_LENGTH_MIN', 6);
define('USER_PASSWORD_LENGTH_MAX', 20);

ユーザ登録

Modelの作成

users.phpを作成し、ユーザ登録・ログイン処理を記述

users.php

// ログイン
function get_user_by_name($db, $name){
    $sql = "
      SELECT
        user_id,
        user_name,
        password
      FROM
        sample_users
      WHERE
        user_name = ?
    ";
    return fetch_query($db, $sql, array($name));
}

function login_as($db, $name, $password){
    $user = get_user_by_name($db, $name);
    if($user === false || $user['password'] !== $password){
        return false;
    }
    set_session('user_id', $user['user_id']);
    return $user;
}

// ユーザ登録
function regist_user($db, $name, $password) {
    if(is_valid_user($name, $password) === false){
        return false;
    }
    return insert_user($db, $name, $password);
}

// バリデーション
function is_valid_user($name, $password){
    // 短絡評価を避けるため一旦代入。
    $is_valid_user_name = is_valid_user_name($name);
    $is_valid_password = is_valid_password($password);
    return $is_valid_user_name && $is_valid_password ;
}

function is_valid_user_name($name) {
    $is_valid = true;
    if(is_valid_length($name, USER_NAME_LENGTH_MIN, USER_NAME_LENGTH_MAX) === false){
      set_error('ユーザー名は'. USER_NAME_LENGTH_MIN . '文字以上、' . USER_NAME_LENGTH_MAX . '文字以内にしてください。');
      $is_valid = false;
    }
    if(is_alphanumeric($name) === false){
      set_error('ユーザー名は半角英数字で入力してください。');
      $is_valid = false;
    }
    return $is_valid;
}

function is_valid_password($password){
    $is_valid = true;
    if(is_valid_length($password, USER_PASSWORD_LENGTH_MIN, USER_PASSWORD_LENGTH_MAX) === false){
      set_error('パスワードは'. USER_PASSWORD_LENGTH_MIN . '文字以上、' . USER_PASSWORD_LENGTH_MAX . '文字以内にしてください。');
      $is_valid = false;
    }
    if(is_alphanumeric($password) === false){
      set_error('パスワードは半角英数字で入力してください。');
      $is_valid = false;
    }
    return $is_valid;
}

// ユーザデータの挿入
function insert_user($db, $name, $password){
    $sql = "
      INSERT INTO
        sample_users(user_name, password)
      VALUES (?,?);
    ";
    return execute_query($db, $sql, array($name, $password));
}
functions.php
// ログイン処理
function is_logined(){
  return get_session('user_id') !== '';
}

// バリデーション
function is_valid_length($string, $minimum_length, $maximum_length = PHP_INT_MAX){
  $length = mb_strlen($string);
  return ($minimum_length <= $length) && ($length <= $maximum_length);
}

function is_alphanumeric($string){
  return is_valid_format($string, REGEXP_ALPHANUMERIC);
}

function is_valid_format($string, $format){
  return preg_match($format, $string) === 1;
}

Viewの作成

※メッセージ表示のところは、繰り返し使用する為、別のファイルに記述し、それを読み込んでいます。

signup_view.php
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>ユーザ登録</title>
  </head>

  <body>
    <h1>ユーザ登録ページ</h1>

    <!-- メッセージ・エラーメッセージ -->
    <?php include VIEW_PATH. 'templates/messages.php'; ?>

    <!-- ログインフォーム -->
    <form method="post" action="signup_process.php">
      <div>
        <label>ユーザ名:</label>
        <input type="text" name="name">
      </div>
      <div>
        <label>パスワード:</label>
        <input type="password" name="password">
      </div>
      <input type="submit" value="新規登録">
      <input type="button" onclick="location.href='<?php print(LOGIN_URL); ?>'" value="ログインページへ">
    </form>
  </body>
</html>

Controllerの作成

signup.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';

session_start();

// ログインされていれば、商品管理ページへ遷移
if(is_logined() === true){
    redirect_to(ADMIN_URL);
}

include_once VIEW_PATH. 'signup_view.php';
signup_process.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'users.php';

session_start();

// ログインされていれば、商品管理ページへ遷移
if(is_logined() === true){
    redirect_to(ADMIN_URL);
}

// Postされたものを定義
$name = get_post('name');
$password = get_post('password');

// データベース接続
$db = get_db_connect();

// ユーザ登録処理
try{
    $result = regist_user($db, $name, $password);
    if($result === false){
        set_error('ユーザ登録に失敗しました。');
        redirect_to(SIGNUP_URL);
    }
}catch(PDOException $e){
    set_error('ユーザ登録に失敗しました。');
    redirect_to(SIGNUP_URL);
}
set_message('ユーザ登録が完了しました。');

// ユーザ登録完了後、そのままログインして商品管理ページへ遷移
login_as($db, $name, $password);
redirect_to(ADMIN_URL);

ログイン

Viewの作成

※メッセージ表示のところは、繰り返し使用する為、別のファイルに記述し、それを読み込んでいます。

login_view.php
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>ログイン</title>
  </head>

  <body>
    <h1>ログインページ</h1>

    <!-- メッセージ・エラーメッセージ -->
    <?php include VIEW_PATH. 'templates/messages.php'; ?>

    <!-- ログインフォーム -->
    <form method="post" action="login_process.php">
      <div>
        <label>ユーザ名</label>
        <input type="text" name="name">
      </div>
      <div>
        <label>パスワード</label>
        <input type="password" name="password">
      </div>
      <input type="submit" value="ログイン">
      <input type="button" onclick="location.href='<?php print(SIGNUP_URL); ?>'" value="ユーザ登録ページへ">
    </form>
  </body>
</html>

Controllerの作成

login.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH . 'functions.php';

session_start();

// ログインされていれば、商品管理ページへ遷移
if(is_logined() === true){
  redirect_to(ADMIN_URL);
}

include_once VIEW_PATH . 'login_view.php';
login_process.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';
require_once MODEL_PATH. 'users.php';

session_start();

// ログインされていれば、商品管理ページへ遷移
if(is_logined() === true){
    redirect_to(ADMIN_URL);
}

// Postされたものを定義
$name = get_post('name');
$password = get_post('password');

// データベース接続
$db = get_db_connect();

// ログイン処理
$user login_as($db, $name, $password);
if($user === false){
    set_error('ログインに失敗しました。');
    redirect_to(LOGIN_URL);
}
set_message('ログインしました。');
redirect_to(ADMIN_URL);

ログアウト

Modelの作成

users.php
// ログイン状況
function get_user($db, $user_id){
    $sql = "
      SELECT
        user_id, 
        user_name,
        password
      FROM
        sample_users
      WHERE
        user_id = ?
    ";
    return fetch_query($db, $sql, array($user_id));
}

function get_login_user($db){
    $login_user_id = get_session('user_id');  
    return get_user($db, $login_user_id);
}  

Viewの作成

遷移先のページに、ログアウトできるよう追記

admin_view.php
<p>ようこそ、<?php print($user['user_name']); ?>さん。</p>
<a href="<?php print(LOGOUT_URL);?>">ログアウト</a>

Controllerの作成

logout.php
<?php
require_once '../conf/const.php';
require_once MODEL_PATH. 'functions.php';

session_start();

$_SESSION = array();
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
  $params["path"],
  $params["domain"],
  $params["secure"],
  $params["httponly"]
);

session_destroy();

redirect_to(LOGIN_URL);
admin.php
require_once MODEL_PATH. 'users.php';

// ログインされてなければ、ログインページへ遷移
if(is_logined() === false){
    redirect_to(LOGIN_URL);
}  

$user = get_login_user($db);

参考

session_get_cookie_params

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2