- 投稿日:2020-08-07T23:58:43+09:00
【PHP入門】ログイン機能
はじめに
今回は、PHPとMySQLを使ってログイン機能を実装していきます。
※当ページは、【PHP入門】CRUD機能で作られたものを前提にしています。バージョン
PHP:7.4.5
phpMyAdmin:5.0.2
MySQL:5.7.30今回作成するファイル
html
- login.php
- login_process.php
- signup.php
- signup_process.php
- logout.phpmodel
- users.phpview
- login_view.php
- signup_view.phpテーブルの作成
bbs_user.sqlCREATE TABLE `bbs_users` ( `user_id` int(11) NOT NULL, `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 `bbs_users` MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (`user_id`);定義
処理に使うものを追記
const.phpdefine('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, name, password FROM bbs_users WHERE 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 bbs_users(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(BBS_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(BBS_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(BBS_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(BBS_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(BBS_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(BBS_URL);ログアウト
Modelの作成
users.php// ログイン状況 function get_user($db, $user_id){ $sql = " SELECT user_id, name, password FROM bbs_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の作成
bbs_view.php<p>ようこそ、<?php print($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);bbs.phprequire_once MODEL_PATH. 'users.php'; // ログインされてなければ、ログインページへ遷移 if(is_logined() === false){ redirect_to(LOGIN_URL); } $user = get_login_user($db);参考
- 投稿日:2020-08-07T18:43:30+09:00
FuelPHPでSQLの最新のレコードを取得する
SQLにあるレコードの、
created_at
が最も新しいものを取得したいといったとき、
SELECTにMAX(created_at)
とするだけでやってくれます。FuelPHPの場合は
example.php$query = \DB::select('id', \DB::expr('MAX(created_at)')) ->from('table_name') ->execute();とするだけでできます。
これに加えて
group_by('id')
などを使うときにすごく役立ちます。配列で取得したあとに頑張って新しい配列に入れるみたいなことをせずに済みます。(自戒)
- 投稿日:2020-08-07T15:02:03+09:00
Laravelでユーザーの生年月日をちゃんと表示する
ユーザーの生年月日をdate型でデータベースに保存するようにします
そのまま表示しようとすると
1998-09-25みたいな表示になるので
format関数を使って○月○日みたいな表示を可能にさせます
モデルの変更
対象となるモデルに記述(ここではUser.php)
User.phpprotected [ 'birthday' ] ## 表示させたいカラムを指定はいこれだけ、
これでformat関数が使えます
あとは指定すれば
<p>{{ $user->birthday->format(Y年m月d年) }}</p>こう表示される
1998年09月25日モデルに設定を記述しないとエラーが出る
- 投稿日:2020-08-07T08:07:16+09:00
MySQLでBOOLEAN型のカラムに'true'をINSERTするとfalseになる
MySQLでBOOLEAN型のカラムに
'true'
をINSERTすると、その値はfalseになります。問題
次のような構造のテーブルがあり、レコードは空の状態だとします。
CREATE TABLE `users` ( `id` INT NOT NULL, `name` TEXT NOT NULL, `status` TEXT NOT NULL, `active` BOOLEAN NOT NULL, PRIMARY KEY (`id`) );このテーブルに対して、レコードを追加してみましょう。
INSERT INTO `users` (`id`, `name`, `status`, `active`) VALUES (1, 'Alice', 'true', 'true');その後、次のようなSQL文を実行するとどうなるでしょうか。
SELECT count(*) FROM users WHERE active = true;結果は、次のようになります。
count(*) 0 それでは、次のようなSQL文を実行するとどうなるでしょうか。
SELECT count(*) FROM users WHERE active = false;結果は、次のようになります。
count(*) 1 これはいったい、なぜしょうか。
原因
レコードを追加したあとのテーブルは、次のような状態になっています。
id name status active 1 Alice true 0 MySQLのBOOLEAN型は実際にはTINYINT(1)型のシノニムで、
0
がfalse、0
以外がtrueを表しています。1
true
という文字列はTINYINT(1)型としては無効な値なので、デフォルト値である0
になってしまったというわけです。解決策
BOOLEAN型のカラムでは、文字列ではなくboolean リテラルで値を書きましょう。2
INSERT INTO `users` (`id`, `name`, `status`, `active`) VALUES (1, 'Alice', 'true', true); INSERT INTO `users` (`id`, `name`, `status`, `active`) VALUES (2, 'Bob', 'true', false);あるいは、対応する数値を使ってもいいでしょう。
INSERT INTO `users` (`id`, `name`, `status`, `active`) VALUES (1, 'Alice', 'true', 1); INSERT INTO `users` (`id`, `name`, `status`, `active`) VALUES (2, 'Bob', 'true', 0);CSVファイルをインポートする場合
LOAD DATA INFILE
構文を用いて次のようなCSVファイルをインポートする場合も、同様の問題が発生します。"id","name","status","active" "1","Alice","true","true" "2","Bob","true","false"この問題を解決するには、インポート時にBOOLEAN型のカラムの値をboolean リテラルに変換します。
LOAD DATA LOCAL INFILE 'users.csv' REPLACE INTO TABLE users FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' IGNORE 1 LINES (id, name, status, @active) SET active = IF(@active='true', true, false);参考リンク