これは、PHPでユーザーアカウント管理システムを作成する方法に関するシリーズのパート4です。他のパーツはここにあります:part1、part2、part3。
これまで、パブリックエリアのユーザー登録とログインについて説明してきました。管理者ユーザーは現在でもログインできますが、管理者ユーザーアカウントの作成にはまだ取り組んでいません。また、ブラウザでhttp://localhost/user-accounts/admin/dashboard.phpと入力するだけで、管理者ユーザーでなくても管理者セクションにアクセスできます。ただし、すぐにすべて修正します。
このパートでは、管理者ユーザーアカウントを作成、更新します。また、ユーザーアカウントを更新する前に、古いパスワードが一致することを確認します。
admin / usersフォルダー内に、次の3つのファイルを作成します。
- userForm.php:ユーザーアカウントを作成および編集するためのフォームが含まれています。
- userList.php:システム上のすべての管理ユーザーを一覧表示します。
- userLogic.php:MVC(Model-View-Controller)の用語では、これをユーザーコントローラーと呼ぶことができます。フォームからのユーザー情報の受信、データベースへの保存、再取得、操作などのロジックが含まれています。
userForm.phpから始めましょう。それを開いて、このコードを貼り付けます。
userForm.php:
<?php include('../../config.php'); ?>
<?php include(INCLUDE_PATH . '/logic/common_functions.php') ?>
<?php include(ROOT_PATH . '/admin/users/userLogic.php'); ?>
<?php $roles = getAllRoles(); ?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>UserAccounts - Create Admin user Account</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<!-- Custome styles -->
<link rel="stylesheet" href="../../assets/css/style.css">
</head>
<body>
<?php include(INCLUDE_PATH . "/layouts/admin_navbar.php") ?>
<div class="container" style="margin-bottom: 150px;">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<a href="userList.php" class="btn btn-primary" style="margin-bottom: 5px;">
<span class="glyphicon glyphicon-chevron-left"></span>
Users
</a>
<br>
<form class="form" action="userForm.php" method="post" enctype="multipart/form-data">
<?php if ($isEditing === true ): ?>
<h2 class="text-center">Update Admin user</h2>
<?php else: ?>
<h2 class="text-center">Create Admin user</h2>
<?php endif; ?>
<hr>
<!-- if editting user, we need that user's id -->
<?php if ($isEditing === true): ?>
<input type="hidden" name="user_id" value="<?php echo $user_id ?>">
<?php endif; ?>
<div class="form-group <?php echo isset($errors['username']) ? 'has-error' : '' ?>">
<label class="control-label">Username</label>
<input type="text" name="username" value="<?php echo $username; ?>" class="form-control">
<?php if (isset($errors['username'])): ?>
<span class="help-block"><?php echo $errors['username'] ?></span>
<?php endif; ?>
</div>
<div class="form-group <?php echo isset($errors['email']) ? 'has-error' : '' ?>">
<label class="control-label">Email Address</label>
<input type="email" name="email" value="<?php echo $email; ?>" class="form-control">
<?php if (isset($errors['email'])): ?>
<span class="help-block"><?php echo $errors['email'] ?></span>
<?php endif; ?>
</div>
<?php if ($isEditing === true ): ?>
<div class="form-group <?php echo isset($errors['passwordOld']) ? 'has-error' : '' ?>">
<label class="control-label">Old Password</label>
<input type="password" name="passwordOld" class="form-control">
<?php if (isset($errors['passwordOld'])): ?>
<span class="help-block"><?php echo $errors['passwordOld'] ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="form-group <?php echo isset($errors['password']) ? 'has-error' : '' ?>">
<label class="control-label">Your Password</label>
<input type="password" name="password" class="form-control">
<?php if (isset($errors['password'])): ?>
<span class="help-block"><?php echo $errors['password'] ?></span>
<?php endif; ?>
</div>
<div class="form-group <?php echo isset($errors['role_id']) ? 'has-error' : '' ?>">
<label class="control-label">User Role</label>
<select class="form-control" name="role_id">
<option value="" ></option>
<?php foreach ($roles as $role): ?>
<?php if ($role['id'] === $role_id): ?>
<option value="<?php echo $role['id'] ?>" selected><?php echo $role['name'] ?></option>
<?php else: ?>
<option value="<?php echo $role['id'] ?>"><?php echo $role['name'] ?></option>
<?php endif; ?>
<?php endforeach; ?>
</select>
<?php if (isset($errors['role_id'])): ?>
<span class="help-block"><?php echo $errors['role_id'] ?></span>
<?php endif; ?>
</div>
<div class="form-group" style="text-align: center;">
<?php if (!empty($profile_picture)): ?>
<img src="<?php echo BASE_URL . '/assets/images/' . $profile_picture; ?>" id="profile_img" style="height: 100px; border-radius: 50%" alt="">
<?php else: ?>
<img src="http://via.placeholder.com/150x150" id="profile_img" style="height: 100px; border-radius: 50%" alt="">
<?php endif; ?>
<input type="file" name="profile_picture" id="profile_input" value="" style="display: none;">
</div>
<div class="form-group">
<?php if ($isEditing === true): ?>
<button type="submit" name="update_user" class="btn btn-success btn-block btn-lg">Update user</button>
<?php else: ?>
<button type="submit" name="save_user" class="btn btn-success btn-block btn-lg">Save user</button>
<?php endif; ?>
</div>
</form>
</div>
</div>
</div>
<?php include(INCLUDE_PATH . "/layouts/footer.php") ?>
<script type="text/javascript" src="../../assets/js/display_profile_image.js"></script>
ブラウザのhttp://localhost/user-accounts/admin/users/userForm.phpでこのページを開くと、未定義のメソッドgetAllRoles()を呼び出していることを示すエラーメッセージが表示されます。この方法が必要なのは、管理者ユーザーを作成するために、データベース内のすべての役割のリストから役割を選択して、このユーザーに割り当てる必要があるためです。したがって、データベースからすべての役割を取得し、フォームのオプション選択フィールドに入力します。
このメソッドは、userLogic.phpファイル内に作成します。そのように:
userLogic.php:
<?php
// variable declaration. These variables will be used in the user form
$user_id = 0;
$role_id = NULL;
$username = "";
$email = "";
$password = "";
$passwordConf = "";
$profile_picture = "";
$isEditing = false;
$users = array();
$errors = array();
function getAllRoles(){
global $conn;
$sql = "SELECT id, name FROM roles";
$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->get_result();
$roles = $result->fetch_all(MYSQLI_ASSOC);
return $roles;
}
ブラウザを更新すると、エラーがなくなり、フォームがページの中央に表示されます。いいね!
フォームの役割のドロップダウンをクリックすると、まだ役割がないことがわかります。これは、データベースに役割テーブルを作成したが、それに役割を追加しなかったためです。 PHPMyAdminまたはお持ちのMySQLクライアントを使用して、データベースのロールテーブルに管理者、編集者、作成者の3つのロールを追加します。
または、このSQL挿入コマンドを実行して、3つの役割すべてを一度に挿入することもできます。
INSERT INTO `roles`(`id`, `name`, `description`)
VALUES (1, 'Admin', 'Has authority of users and roles and permissions.' ),
(2, 'Author', 'Has full authority of own posts'),
(3, 'Editor', 'Has full authority over all posts')
ページをリロードすると、これらの役割が役割選択フィールドで使用できるようになります。
現時点では、まだユーザーを作成できません。しかし、フォームはすべて設定されています。残っているのは、フォームから送信された値を受け取るコードだけです。このコードをuserLogic.phpファイルに配置します。もう一度開いて、ユーザーの作成、更新、編集、削除に必要な残りのコードを追加しましょう。
userLogic.php:
// ... variables declaration is up here ...
// ACTION: update user
if (isset($_POST['update_user'])) { // if user clicked update_user button ...
$user_id = $_POST['user_id'];
updateUser($user_id);
}
// ACTION: Save User
if (isset($_POST['save_user'])) { // if user clicked save_user button ...
saveUser();
}
// ACTION: fetch user for editting
if (isset($_GET["edit_user"])) {
$user_id = $_GET["edit_user"];
editUser($user_id);
}
// ACTION: Delete user
if (isset($_GET['delete_user'])) {
$user_id = $_GET['delete_user'];
deleteUser($user_id);
}
function updateUser($user_id) {
global $conn, $errors, $username, $role_id, $email, $isEditing;
$errors = validateUser($_POST, ['update_user', 'update_profile']);
// receive all input values from the form
$username = $_POST['username'];
$email = $_POST['email'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT); //encrypt the password before saving in the database
$profile_picture = uploadProfilePicture();
if (count($errors) === 0) {
if (isset($_POST['role_id'])) {
$role_id = $_POST['role_id'];
}
$sql = "UPDATE users SET username=?, role_id=?, email=?, password=?, profile_picture=? WHERE id=?";
$result = modifyRecord($sql, 'sisssi', [$username, $role_id, $email, $password, $profile_picture, $user_id]);
if ($result) {
$_SESSION['success_msg'] = "User account successfully updated";
header("location: " . BASE_URL . "admin/users/userList.php");
exit(0);
}
} else {
// continue editting if there were errors
$isEditing = true;
}
}
// Save user to database
function saveUser(){
global $conn, $errors, $username, $role_id, $email, $isEditing;
$errors = validateUser($_POST, ['save_user']);
// receive all input values from the form
$username = $_POST['username'];
$email = $_POST['email'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT); //encrypt the password before saving in the database
$profile_picture = uploadProfilePicture(); // upload profile picture and return the picture name
if (count($errors) === 0) {
if (isset($_POST['role_id'])) {
$role_id = $_POST['role_id'];
}
$sql = "INSERT INTO users SET username=?, role_id=?, email=?, password=?, profile_picture=?";
$result = modifyRecord($sql, 'sisss', [$username, $role_id, $email, $password, $profile_picture]);
if($result){
$_SESSION['success_msg'] = "User account created successfully";
header("location: " . BASE_URL . "admin/users/userList.php");
exit(0);
} else {
$_SESSION['error_msg'] = "Something went wrong. Could not save user in Database";
}
}
}
function getAdminUsers(){
global $conn;
// for every user, select a user role name from roles table, and then id, role_id and username from user table
// where the role_id on user table matches the id on roles table
$sql = "SELECT r.name as role, u.id, u.role_id, u.username
FROM users u
LEFT JOIN roles r ON u.role_id=r.id
WHERE role_id IS NOT NULL AND u.id != ?";
$users = getMultipleRecords($sql, 'i', [$_SESSION['user']['id']]);
return $users;
}
function editUser($user_id){
global $conn, $user_id, $role_id, $username, $email, $isEditing, $profile_picture;
$sql = "SELECT * FROM users WHERE id=?";
$user = getSingleRecord($sql, 'i', [$user_id]);
$user_id = $user['id'];
$role_id = $user['role_id'];
$username = $user['username'];
$profile_picture = $user['profile_picture'];
$email = $user['email'];
$isEditing = true;
}
function deleteUser($user_id) {
global $conn;
$sql = "DELETE FROM users WHERE id=?";
$result = modifyRecord($sql, 'i', [$user_id]);
if ($result) {
$_SESSION['success_msg'] = "User trashed!!";
header("location: " . BASE_URL . "admin/users/userList.php");
exit(0);
}
}
フォームに入力せずに[ユーザーを保存]ボタンをクリックすると、検証メッセージがフォームに表示されます。しばらく前に定義したものと同じvalidateUser()関数を使用しています。したがって、コードをそのようなメソッドにリファクタリングすることで、コードを繰り返す必要がなくなることがわかります。画像のアップロードでさえ、前のチュートリアルの1つで定義されたuploadProfileImage()によって処理されます。
最初の管理者ユーザーを作成しましょう。フォームに記入し、[ユーザーを保存]ボタンをクリックします。これにより、管理者ユーザーがデータベースに保存され、現在は空のuserList.phpページにリダイレクトされます。
userList.phpファイルは、データベースで使用可能な管理ユーザーをリストすることになっています。それでは、そのためのコードを書いてみましょう。
userList.php:
<?php include('../../config.php') ?>
<?php include(ROOT_PATH . '/admin/users/userLogic.php') ?>
<?php
$adminUsers = getAdminUsers();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin Area - Users </title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<!-- Custome styles -->
<link rel="stylesheet" href="../../static/css/style.css">
</head>
<body>
<?php include(INCLUDE_PATH . "/layouts/admin_navbar.php") ?>
<div class="col-md-8 col-md-offset-2">
<a href="userForm.php" class="btn btn-success">
<span class="glyphicon glyphicon-plus"></span>
Create new user
</a>
<hr>
<h1 class="text-center">Admin Users</h1>
<br />
<?php if (isset($users)): ?>
<table class="table table-bordered">
<thead>
<tr>
<th>N</th>
<th>Username</th>
<th>Role</th>
<th colspan="2" class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($adminUsers as $key => $value): ?>
<tr>
<td><?php echo $key + 1; ?></td>
<td><?php echo $value['username'] ?></td>
<td><?php echo $value['role']; ?></td>
<td class="text-center">
<a href="<?php echo BASE_URL ?>admin/users/userForm.php?edit_user=<?php echo $value['id'] ?>" class="btn btn-sm btn-success">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</td>
<td class="text-center">
<a href="<?php echo BASE_URL ?>admin/users/userForm.php?delete_user=<?php echo $value['id'] ?>" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-trash"></span>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<h2 class="text-center">No users in database</h2>
<?php endif; ?>
</div>
<?php include(INCLUDE_PATH . "/layouts/footer.php") ?>
</body>
</html>
少し前のuserLogic.phpファイルに、getAdminUsers()というメソッドを含めました。このメソッドは、表示するデータベースからすべての管理者ユーザーを選択します。
ブラウザのuserList.phpページを更新するだけで、出来上がりです。最初の管理者ユーザーがテーブルにリストされています。鉛筆アイコンの付いた緑色のボタンをクリックして、ユーザーを編集します。ゴミ箱アイコンの付いた赤いボタンをクリックして、ユーザーを削除することもできます。
ユーザーの役割
これで、ユーザーを作成してユーザーに役割を割り当てることができますが、システムに別の役割を追加したい場合はどうでしょうか。役割を作成するたびに、データベースで直接コマンドを実行することに頼ることはできませんよね?このセクションを、役割の作成、更新、削除で締めくくりましょう。
admin / rolesフォルダーに移動し、roleForm.php、roleList.php、roleLogic.phpの3つのファイルを作成します。 (usersフォルダーに似ていますか?)
roleForm.php:
<?php include('../../config.php') ?>
<?php include(ROOT_PATH . '/includes/logic/common_functions.php') ?>
<?php include(ROOT_PATH . '/admin/roles/roleLogic.php') ?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin - Create new role </title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<!-- Custom styles -->
<link rel="stylesheet" href="../../static/css/style.css">
</head>
<body>
<?php include(INCLUDE_PATH . "/layouts/admin_navbar.php") ?>
<div class="col-md-8 col-md-offset-2">
<a href="roleList.php" class="btn btn-primary">
<span class="glyphicon glyphicon-chevron-left"></span>
Roles
</a>
<hr>
<form class="form" action="roleForm.php" method="post">
<?php if ($isEditting === true): ?>
<h1 class="text-center">Update Role</h1>
<?php else: ?>
<h1 class="text-center">Create Role</h1>
<?php endif; ?>
<br />
<?php if ($isEditting === true): ?>
<input type="hidden" name="role_id" value="<?php echo $role_id ?>">
<?php endif; ?>
<div class="form-group <?php echo isset($errors['name']) ? 'has-error': '' ?>">
<label class="control-label">Role name</label>
<input type="text" name="name" value="<?php echo $name; ?>" class="form-control">
<?php if (isset($errors['name'])): ?>
<span class="help-block"><?php echo $errors['name'] ?></span>
<?php endif; ?>
</div>
<div class="form-group <?php echo isset($errors['description']) ? 'has-error': '' ?>">
<label class="control-label">Description</label>
<textarea name="description" value="<?php echo $description; ?>" rows="3" cols="10" class="form-control"><?php echo $description; ?></textarea>
<?php if (isset($errors['description'])): ?>
<span class="help-block"><?php echo $errors['description'] ?></span>
<?php endif; ?>
</div>
<div class="form-group">
<?php if ($isEditting === true): ?>
<button type="submit" name="update_role" class="btn btn-primary">Update Role</button>
<?php else: ?>
<button type="submit" name="save_role" class="btn btn-success">Save Role</button>
<?php endif; ?>
</div>
</form>
</div>
<?php include(INCLUDE_PATH . "/layouts/footer.php") ?>
</body>
</html>
これは、ユーザーの場合と非常によく似ているため、ここではあまり説明しません。次に、roleLogic.phpに進み、ロールの作成、更新、削除に必要なコードを記述します。
roleLogic.php:
<?php
$role_id = 0;
$name = "";
$description = "";
$isEditting = false;
$roles = array();
$errors = array();
// ACTION: update role
if (isset($_POST['update_role'])) {
$role_id = $_POST['role_id'];
updateRole($role_id);
}
// ACTION: Save Role
if (isset($_POST['save_role'])) {
saveRole();
}
// ACTION: fetch role for editting
if (isset($_GET["edit_role"])) {
$role_id = $_GET['edit_role'];
editRole($role_id);
}
// ACTION: Delete role
if (isset($_GET['delete_role'])) {
$role_id = $_GET['delete_role'];
deleteRole($role_id);
}
// Save role to database
function saveRole(){
global $conn, $errors, $name, $description;
$errors = validateRole($_POST, ['save_role']);
if (count($errors) === 0) {
// receive form values
$name = $_POST['name'];
$description = $_POST['description'];
$sql = "INSERT INTO roles SET name=?, description=?";
$result = modifyRecord($sql, 'ss', [$name, $description]);
if ($result) {
$_SESSION['success_msg'] = "Role created successfully";
header("location: " . BASE_URL . "admin/roles/roleList.php");
exit(0);
} else {
$_SESSION['error_msg'] = "Something went wrong. Could not save role in Database";
}
}
}
function updateRole($role_id){
global $conn, $errors, $name, $isEditting; // pull in global form variables into function
$errors = validateRole($_POST, ['update_role']); // validate form
if (count($errors) === 0) {
// receive form values
$name = $_POST['name'];
$description = $_POST['description'];
$sql = "UPDATE roles SET name=?, description=? WHERE id=?";
$result = modifyRecord($sql, 'ssi', [$name, $description, $role_id]);
if ($result) {
$_SESSION['success_msg'] = "Role successfully updated";
$isEditting = false;
header("location: " . BASE_URL . "admin/roles/roleList.php");
exit(0);
} else {
$_SESSION['error_msg'] = "Something went wrong. Could not save role in Database";
}
}
}
function editRole($role_id){
global $conn, $name, $description, $isEditting;
$sql = "SELECT * FROM roles WHERE id=? LIMIT 1";
$role = getSingleRecord($sql, 'i', [$role_id]);
$role_id = $role['id'];
$name = $role['name'];
$description = $role['description'];
$isEditting = true;
}
function deleteRole($role_id) {
global $conn;
$sql = "DELETE FROM roles WHERE id=?";
$result = modifyRecord($sql, 'i', [$role_id]);
if ($result) {
$_SESSION['success_msg'] = "Role trashed!!";
header("location: " . BASE_URL . "admin/roles/roleList.php");
exit(0);
}
}
function getAllRoles(){
global $conn;
$sql = "SELECT id, name FROM roles";
$roles = getMultipleRecords($sql);
return $roles;
}
ただし、[役割の保存]ボタンをクリックすると、未定義のvalidateRole()メソッドに関する警告が表示されます。ユーザーのvalidateUser()と同様に、このvalidateRole()メソッドをcommon_functions.phpファイルに追加します。したがって、ファイルを開いて、この関数をファイルの下部に追加します。
common_functions.php:
// ... other functions up here ...
// Accept a post object, validates post and return an array with the error messages
function validateRole($role, $ignoreFields) {
global $conn;
$errors = [];
foreach ($role as $key => $value) {
if (in_array($key, $ignoreFields)) {
continue;
}
if (empty($role[$key])) {
$errors[$key] = "This field is required";
}
}
return $errors;
}
もう一度[役割の保存]ボタンをクリックすると、エラーメッセージが表示されます。
次はroleList.phpファイルです。
roleList.php:
<?php include('../../config.php') ?>
<?php include(ROOT_PATH . '/admin/roles/roleLogic.php') ?>
<?php
$roles = getAllRoles();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin Area - User Roles </title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<!-- Custome styles -->
<link rel="stylesheet" href="../../static/css/style.css">
</head>
<body>
<?php include(INCLUDE_PATH . "/layouts/admin_navbar.php") ?>
<div class="col-md-8 col-md-offset-2">
<a href="roleForm.php" class="btn btn-success">
<span class="glyphicon glyphicon-plus"></span>
Create new role
</a>
<hr>
<h1 class="text-center">User Roles</h1>
<br />
<?php if (isset($roles)): ?>
<table class="table table-bordered">
<thead>
<tr>
<th>N</th>
<th>Role name</th>
<th colspan="3" class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($roles as $key => $value): ?>
<tr>
<td><?php echo $key + 1; ?></td>
<td><?php echo $value['name'] ?></td>
<td class="text-center">
<a href="<?php echo BASE_URL ?>admin/roles/assignPermissions.php?assign_permissions=<?php echo $value['id'] ?>" class="btn btn-sm btn-info">
permissions
</a>
</td>
<td class="text-center">
<a href="<?php echo BASE_URL ?>admin/roles/roleForm.php?edit_role=<?php echo $value['id'] ?>" class="btn btn-sm btn-success">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</td>
<td class="text-center">
<a href="<?php echo BASE_URL ?>admin/roles/roleForm.php?delete_role=<?php echo $value['id'] ?>" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-trash"></span>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<h2 class="text-center">No roles in database</h2>
<?php endif; ?>
</div>
<?php include(INCLUDE_PATH . "/layouts/footer.php") ?>
</body>
</html>
ブラウザで、http://localhost/user-accounts/admin/roles/roleList.phpにアクセスします。そして今、私たちは役割を作成、編集、更新、削除することもできます。
もう一度フォローしていただきありがとうございます。うまくいけば、次のパートで、権限とユーザープロファイルの編集に取り組んでいます。