Questa è la parte 4 di una serie su come creare un sistema di gestione degli account utente in PHP. Puoi trovare le altre parti qui:parte 1, parte 2, parte 3.
Finora abbiamo trattato la registrazione degli utenti e l'accesso all'area pubblica. Un utente amministratore può accedere anche così com'è ora, ma non abbiamo ancora lavorato alla creazione di account utente amministratore. Inoltre, se inserisci http://localhost/user-accounts/admin/dashboard.php sul browser, puoi accedere alla sezione amministratore senza essere un utente amministratore. Ma risolveremo tutto al più presto.
In questa parte creeremo e aggiorneremo gli account utente amministratore. Verificheremo inoltre che la vecchia password corrisponda prima di aggiornare un account utente.
All'interno della cartella admin/users, crea questi 3 file:
- userForm.php:contiene il modulo per la creazione e la modifica degli account utente.
- userList.php:elenca tutti gli utenti amministrativi sul sistema.
- userLogic.php:nel gergo MVC (Model-View-Controller) , possiamo riferirci a questo come controller utente. Contiene la logica come ricevere le informazioni sull'utente dal modulo, salvarlo nel database, recuperarlo di nuovo, manipolarlo e così via.
Iniziamo con userForm.php. Aprilo e incollaci questo codice.
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>
Se apriamo questa pagina nel nostro browser all'indirizzo http://localhost/user-accounts/admin/users/userForm.php, viene visualizzato un messaggio di errore che dice che stiamo chiamando un metodo non definito getAllRoles(). Abbiamo bisogno di questo metodo perché, per creare un utente admin, dobbiamo selezionare un ruolo dall'elenco di tutti i ruoli nel database da assegnare a questo utente. Quindi otterremo tutti i ruoli dal database e li popoleremo in un campo di selezione delle opzioni nel modulo.
Creeremo questo metodo all'interno del file userLogic.php. Così:
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;
}
Aggiorna ora sul tuo browser vedrai che l'errore è scomparso e il nostro modulo ora è pulito al centro della pagina. Bello!
Se fai clic sul menu a discesa dei ruoli nel modulo, noterai che non ci sono ancora ruoli. Questo perché abbiamo creato la tabella dei ruoli nel database ma non abbiamo aggiunto ruoli ad essa. Usando PHPMyAdmin o qualsiasi client MySQL di cui disponi, aggiungi i seguenti tre ruoli nella tabella dei ruoli nel nostro database:Admin, Editor e Author.
Oppure puoi semplicemente eseguire questo comando di inserimento SQL per inserire tutti e tre i ruoli contemporaneamente:
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')
Se ricarichi la pagina, questi ruoli saranno ora disponibili nel campo di selezione del tuo ruolo.
A questo punto, non possiamo ancora creare un utente. Ma il modulo è tutto pronto. Non resta che il codice che riceve i valori inseriti dal form. Metteremo questo codice nel file userLogic.php. Aprilo ancora una volta e aggiungiamo il codice rimanente necessario per creare, aggiornare, modificare ed eliminare l'utente.
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);
}
}
Senza compilare il modulo, fai clic sul pulsante 'Salva utente' e vedrai che i messaggi di convalida appaiono sul modulo. Stiamo usando la stessa funzione validateUser() che abbiamo definito tempo fa. Quindi vedi come il refactoring del nostro codice in tali metodi ci salva dalla ripetizione del codice. Anche il caricamento delle immagini è gestito dall'uploadProfileImage() che aveva definito in uno dei tutorial precedenti.
Creiamo il nostro primo utente amministratore. Compila il modulo e fai clic sul pulsante "Salva utente". Questo salva il nostro utente amministratore nel database e reindirizza alla pagina userList.php che per ora è vuota.
Il file userList.php dovrebbe elencare gli utenti amministratori disponibili nel database. Quindi scriviamo il codice per questo.
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>
Nel nostro file userLogic.php di qualche tempo fa, abbiamo incluso un metodo chiamato getAdminUsers(). Questo metodo seleziona tutti gli utenti amministratori dal database da visualizzare.
Basta aggiornare la pagina userList.php sul browser e voilà! Abbiamo il nostro primo utente amministratore elencato su una tabella. Fare clic sul pulsante verde con l'icona a forma di matita per modificare l'utente. Puoi anche fare clic sul pulsante rosso con l'icona del cestino per eliminare l'utente.
Ruoli utente
Ora possiamo creare il nostro utente e assegnare loro ruoli, ma cosa succede se vogliamo aggiungere un altro ruolo al sistema? Non possiamo fare affidamento sull'esecuzione di un comando direttamente sul nostro database ogni volta che vogliamo creare un ruolo, giusto? Concludiamo questa sezione con Creazione, aggiornamento ed eliminazione di ruoli.
Passa alla cartella admin/roles e crea tre file:roleForm.php, roleList.php e roleLogic.php. (Simile alla cartella degli utenti, no?)
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>
Questo è molto simile a quello che abbiamo fatto nel caso degli utenti, quindi non farò molte spiegazioni qui. Procediamo ora al roleLogic.php dove scriviamo il codice necessario per creare, aggiornare ed eliminare i ruoli.
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;
}
Ma quando fai clic sul pulsante "Salva ruolo", viene visualizzato un avviso su un metodo validateRole() non definito. Proprio come validateUser() per gli utenti, aggiungeremo questo metodo validateRole() nel nostro file common_functions.php. Quindi apri il file e aggiungi questa funzione in fondo.
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;
}
Fai di nuovo clic sul pulsante Salva ruolo e vedrai i messaggi di errore visualizzati.
Il prossimo è il file 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>
Sul tuo browser, vai a http://localhost/user-accounts/admin/roles/roleList.php. E ora possiamo anche creare, modificare, aggiornare ed eliminare ruoli.
Ancora una volta grazie per aver seguito. Spero di vederti nella prossima parte in cui lavoreremo sulle autorizzazioni e sulla modifica del profilo utente.