Sunteți pe pagina 1din 48

Skip to content

 Learn
o Basic HTML
o Basic CSS
o Basic Javascript
o Responsive CSS
 Tips & Tutorials
o PHP
o Javascript
o HTML & CSS
o Others
 Projects
o Cart Boxx
o Invoicr
 Recommendations
 Search

3 Steps Simple PHP User Role Management


System
Share





INTRODUCTION
THE PERMISSIONS HEADACHE
Welcome to a tutorial on how to create a simple PHP User Role Management System. So you
have a project that needs to identify and restrict what each user is able to do – Creating a
permissions structure is often quite a grueling task, but I shall share my simple solution in this
guide. Read on!

I have included a zip file with all the source code at the end of this tutorial, so you don’t have to
copy-paste everything… Or if you just want the code and skip the tutorial.
CONFESSION
AN HONEST DISCLOSURE

Quick, hide your wallets! I am an affiliate partner of Google, eBay, Adobe, Bluehost, Clickbank,
and more. There are affiliate links and advertisements throughout this website. Whenever you
buy things from the evil links that I recommend, I will make a commission. Nah. These are just
things to keep the blog going, and allows me to give more good stuff to you guys - for free. So
thank you if you decide to pick up my recommendations!

NAVIGATION
TABLE OF CONTENTS

Prelude Step 1 Step 2


Overview & Assumptions The Database The Base Library

Step 3 Extra Closing


Add The Checks! Download & More What’s Next?
PRELUDE
OVERVIEW & ASSUMPTIONS

Before we dive into the code, let us start with an overview of the entire project, plus some
assumptions that I have made – So you know what to expect from this guide.

THE SYSTEM STRUCTURE


I am sure that everyone here already has an existing website, and it follows the “universal”
structure of:

 Database – Storing all your users’ data and stuff.


 Server-side Scripts – A set of library files and process handlers.
 Client-side Scripts – Front-end user interface.

Thus, I shall assume that you guys already have some sort of a user database, admin panel, and
login mechanism – We will not reinvent the wheel in this guide and come up with another user
login system plus admin interface. What we will focus on, are the database, the libraries, plus the
concepts of a user role/permission system.

We will not build any nice looking user interfaces in this guide, but touch more on the technical
changes you need to make on your existing system. Also, I shall assume that you guys are
already veteran code ninjas who are comfortable with PHP, HTML, CSS, Javascript, AJAX, and
SQL… That I will not need to explain the tiny boring details of “how HTML and CSS work”.
STEP 1
THE DATABASE

Let us now start with the foundations of the system, the database – Don’t worry if you have not
created a users database yet, I shall provide a complete working system here.

1A) THE TABLES

There are 4 tables involved in this project:


 Permissions – To keep track of actions that require permission. For example, accessing
the list of users, and creating new users.
 Roles – Names of the roles. For examples, administrators, editors, etc…
 Roles-Permissions – To specify which role has which permissions.
 Users -Your list of users and their roles.

1B) THE SQL

permissions.sql
-- [USER TABLE]
-- ! JUST ADD A ROLE_ID IF YOU HAVE AN EXISTING TABLE !
CREATE TABLE `users` (
`user_id` int(11) NOT NULL,
`user_email` varchar(255) NOT NULL,
`user_name` varchar(255) NOT NULL,
`user_password` varchar(255) NOT NULL,
`role_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `users`


ADD PRIMARY KEY (`user_id`),
ADD UNIQUE KEY `user_email` (`user_email`),
ADD KEY `user_name` (`user_name`);

ALTER TABLE `users`


MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT;

-- [PERMISSIONS TABLES]
CREATE TABLE `permissions` (
`perm_mod` varchar(5) NOT NULL,
`perm_id` int(11) NOT NULL,
`perm_desc` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `permissions`


ADD PRIMARY KEY (`perm_mod`,`perm_id`);

CREATE TABLE `roles` (


`role_id` int(11) NOT NULL,
`role_name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `roles`


ADD PRIMARY KEY (`role_id`),
ADD UNIQUE KEY `role_name` (`role_name`);

ALTER TABLE `roles`


MODIFY `role_id` int(11) NOT NULL AUTO_INCREMENT;

CREATE TABLE `roles_permissions` (


`role_id` int(11) NOT NULL,
`perm_mod` varchar(5) NOT NULL,
`perm_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `roles_permissions`


ADD PRIMARY KEY (`role_id`,`perm_mod`,`perm_id`);
Users
Field Description
user_id The user ID, auto-increment and primary key.
user_email User’s email. Set to unique to prevent duplicate registrations.
user_name The user’s name. Indexed, for fast searches.
user_password User password.
role_id Role of the user.

If you already have an existing users table, just add a role ID to it.

Permissions
Field Description
The module, an abbreviation code up to 5 characters. For example “USR” for users,
perm_mod
“INV” for inventory. Partial primary key.
perm_id Permissions ID, just a running number. Partial primary key.
perm_desc Permission description. For example, access inventory list, create a new user, etc…
Roles
Field Description
role_id Role ID, primary key and auto-increment.
role_name Name of the role. For example, an administrator.
Role Permissions
Field Description
role_id Role ID, partial primary key.
perm_mod Module code, partial primary key.
perm_id Permission ID, partial primary key.

That’s it for the tables, but please do remember to add more of your own permissions and roles.

1C) SAMPLE DATA

This is the set of dummy data that we will use as examples in this guide.

sample.sql
-- [DUMMY DATA]
-- USER PASSWORD IS 123456
INSERT INTO `users` (`user_id`, `user_email`, `user_name`, `user_password`,
`role_id`) VALUES
(1, 'john@doe.com', 'John Doe',
'$2y$10$EIPcGzgNnfpZM9gkm3GqiuNaGjZuJwdCggOVrwzJ6olNQqqRmCH5i', 1),
(2, 'jane@doe.com', 'Jane Doe',
'$2y$10$EIPcGzgNnfpZM9gkm3GqiuNaGjZuJwdCggOVrwzJ6olNQqqRmCH5i', 2);

INSERT INTO `permissions` (`perm_mod`, `perm_id`, `perm_desc`) VALUES


('USR', 1, 'Access users'),
('USR', 2, 'Create new users'),
('USR', 3, 'Update users'),
('USR', 4, 'Delete users');

INSERT INTO `roles` (`role_id`, `role_name`) VALUES


(1, 'Administrator'),
(2, 'Power User');

INSERT INTO `roles_permissions` (`role_id`, `perm_mod`, `perm_id`) VALUES


(1, 'USR', 1),
(1, 'USR', 2),
(1, 'USR', 3),
(1, 'USR', 4),
(2, 'USR', 1);

STEP 2
THE BASE LIBRARY

With the database foundations established, we shall now build the libraries for permissions
checking.

2A) THE CONFIG FILE

config.php
<?php
// MUTE NOTICES
error_reporting(E_ALL & ~E_NOTICE);

// DATABASE SETTINGS - CHANGE THESE TO YOUR OWN


define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_CHARSET', 'utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
?>

If you have not already created a config file, it is time to do so. There is nothing much to it, just
remember to change the database settings to your own.

2B) THE BASE LIBRARY

lib-db.php
<?php
class Base {
private $pdo = null;
private $stmt = null;
public $error = "";
public $lastID = null;

function __construct() {
// __construct() : connect to the database
// PARAM : DB_HOST, DB_CHARSET, DB_NAME, DB_USER, DB_PASSWORD

// ATTEMPT CONNECT
try {
$str = "mysql:host=" . DB_HOST . ";charset=" . DB_CHARSET;
if (defined('DB_NAME')) { $str .= ";dbname=" . DB_NAME; }
$this->pdo = new PDO(
$str, DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
return true;
}

// ERROR - DO SOMETHING HERE


// THROW ERROR MESSAGE OR SOMETHING
catch (Exception $ex) {
print_r($ex);
die();
}
}

function __destruct() {
// __destruct() : close connection when done

if ($this->stmt !== null) { $this->stmt = null; }


if ($this->pdo !== null) { $this->pdo = null; }
}

function start() {
// start() : auto-commit off

$this->pdo->beginTransaction();
}

function end($commit=1) {
// end() : commit or roll back?

if ($commit) { $this->pdo->commit(); }
else { $this->pdo->rollBack(); }
}

function exec($sql, $data=null) {


// exec() : run insert, replace, update, delete query
// PARAM $sql : SQL query
// $data : array of data

try {
$this->stmt = $this->pdo->prepare($sql);
$this->stmt->execute($data);
$this->lastID = $this->pdo->lastInsertId();
} catch (Exception $ex) {
$this->error = $ex;
return false;
}
$this->stmt = null;
return true;
}

function fetch($sql, $cond=null, $key=null, $value=null) {


// fetch() : perform select query
// PARAM $sql : SQL query
// $cond : array of conditions
// $key : sort in this $key=>data order, optional
// $value : $key must be provided, sort in $key=>$value order

$result = false;
try {
$this->stmt = $this->pdo->prepare($sql);
$this->stmt->execute($cond);
if (isset($key)) {
$result = array();
if (isset($value)) {
while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) {
$result[$row[$key]] = $row[$value];
}
} else {
while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) {
$result[$row[$key]] = $row;
}
}
} else {
$result = $this->stmt->fetchAll();
}
} catch (Exception $ex) {
$this->error = $ex;
return false;
}
$this->stmt = null;
return $result;
}

function check($perm, $mod="") {


// check() : checks if user has sufficient access rights
// PARAM $perm : permission ID
// $mod : module code
// !! USER MUST BE SIGNED IN FIRST !!

// INIT
$pass = true;
if ($mod=="") { $mod = $this->modcode; }

// NOT SIGNED IN
// OR USER DOES NOT HAVE PERMISSION TO ENTIRE MODULE
if (!is_array($_SESSION['user']['perm'][$mod])) { $pass = false; }

// CHECK SPECIFIC PERMISSION


if (!in_array($perm, $_SESSION['user']['perm'][$mod])) { $pass = false; }

// RETURN ACCESS CHECK


if (!$pass) { $this->error = "You do not have sufficient access rights.";
}
return $pass;
}
}
?>
Function Description
__construct The constructor, automatically connects to the database when the object is created.
The destructor, automatically disconnects from the database when the object is
__destructor
destroyed.
start Auto-commit off. Used for multiple queries, in conjunction with end.
To commit or rollback the queries. Used for multiple queries, in conjunction with
end
start.
exec Executes insert, replace, update, and delete queries.
fetch Executes select query.
check Checks if the user has access to the given module/action.

Yep, this is actually a database library that we will be building the rest of the system upon. The
key function that you have to take note here is check.

STEP 3
ADDING CHECKS
With the database and base library, all that is left to do to complete the puzzle is to integrate the
actual checks.

3A) CHECKS IN LIBRARY FILES

Just how the heck do we use the base library and do the checks? Let us start by creating a users
library as an example.

lib-users.php
<?php
class Users extends Base {
protected $modcode = "USR";
function in($email, $password) {
// in() : sign in given user

// Get user
$entry = $this->fetch(
"SELECT * FROM `users` LEFT JOIN `roles` USING (`role_id`) WHERE
`user_email`=?",
[$email]
);
if (count($entry)==0) { return false; }
else {
// Verify password
$entry = $entry[0];
if (password_verify($password, $entry['user_password'])) {
$_SESSION['user'] = [
"user_id" => $entry['user_id'],
"role_id" => $entry['role_id'],
"role_name" => $entry['role_name'],
"user_email" => $entry['user_email'],
"user_name" => $entry['user_name']
];
// Get permissions
$entry = $this->fetch(
"SELECT * FROM `roles_permissions` WHERE `role_id`=?",
[$entry['role_id']]
);
if (is_array($entry)) {
$_SESSION['user']['perm'] = [];
foreach ($entry as $e) {
if (!is_array($_SESSION['user']['perm'][$e['perm_mod']])) {
$_SESSION['user']['perm'][$e['perm_mod']] = [];
}
$_SESSION['user']['perm'][$e['perm_mod']][] = $e['perm_id'];
}
}
} else { return false; }
}
return true;
}

function get($id) {
// get() : get user
// PARAM $id : user ID or email

// ACCESS CHECK
if (!$this->check(1)) { return false; }

// FETCH
$sql = sprintf("SELECT * FROM `users` LEFT JOIN `roles` USING (`role_id`)
WHERE `user_%s`=?",
is_numeric($id) ? "id" : "email"
);
$entry = $this->fetch($sql, [$id]);
return count($entry)==0 ? false : $entry[0] ;
}

function add($email, $name, $password, $role) {


// add() : add a new user
// PARAM $email : email address
// $name : user name
// $password : plain text password
// $role : role ID

// ACCESS CHECK
if (!$this->check(2)) { return false; }

// INSERT
return $this->exec(
"INSERT INTO `users` (`user_email`, `user_name`, `user_password`,
`role_id`) VALUES (?, ?, ?, ?)",
[$email, $name, password_hash($password, PASSWORD_DEFAULT), $role]
);
}

function edit($email, $name, $password, $role, $id) {


// edit() : update an existing user
// PARAM $email : email address
// $name : user name
// $password : plain text password
// $role : role ID
// $id : user ID

// ACCESS CHECK
if (!$this->check(3)) { return false; }

// UPDATE
return $this->exec(
"UPDATE `users` SET `user_email`=?, `user_name`=?, `user_password`=?,
`role_id`=? WHERE `user_id`=?",
[$email, $name, password_hash($password, PASSWORD_DEFAULT), $role, $id]
);
}

function delete($id) {
// delete() : delete user
// PARAM $id : user ID

// ACCESS CHECK
if (!$this->check(4)) { return false; }

// DELETE
return $this->exec(
"DELETE FROM `users` WHERE `user_id`=?",
[$id]
);
}
}
?>
Function Description
Sign in the given user – Will populate$_SESSION['user'] with the user and access
in
permissions. Make sure that the session is started before calling this function!
get Get the given user ID or email.
add Add a new user.
edit Update an existing user.
delete Delete the existing user.

Let us now follow up with how the permissions checking work:

1. This users library is a child of the base class. Meaning, it inherits all the database and
check functions.
2. The users library is given the module code of “USR” with protected $modcode =
"USR";
3. Before running the functions get, add, edit, and delete – There will be an access
permission check.
4. The check function will simply match against the user session to see if the user has
access rights for the given module code and permission ID.

3B) SET THE PERMISSIONS IN THE SESSION!

So yep, the key is to first put the access permissions into session upon login – You can recycle
my user library and login function in your own project if you wish.

eg-1-login.php
<?php
// INIT
session_start();
require "config.php";
require "lib-base.php";
require "lib-users.php";

// LOGIN
echo $libUsr->in("john@doe.com", "123456") ? "OK" : $libUsr->error ;
print_r($_SESSION);
?>

3C) EVERYTHING SHOULD AUTOMATICALLY FALL IN PLACE

Once those are done, everything should pretty much automatically fall in place. For example, the
library functions will only run when the user has sufficient access rights:

eg-2-ajax.php
<?php
// INIT
session_start();
require "config.php";
require "lib-base.php";
require "lib-users.php";

// ADD NEW USER


echo $libUsr->add($_POST['email'], $_POST['name'], $_POST['password'],
$_POST['role'])
? "OK"
: $libUsr->error ;
?>

Or you can directly use the check function to restrict access to certain pages:

eg-3-page.php
<?php
// INIT
session_start();
require "config.php";
require "lib-base.php";
require "lib-users.php";

// CHECK ACCESS TO PAGE


if (!$libUsr->check(1)) {
die("You do not have access to this page.");
} ?>
<!DOCTYPE html>
<html>
<body>Yes, you can access the users management page</body>
</html>
EXTRA
DOWNLOAD & MORE

That’s it for all the code, and here is the download as promised plus a small extra that you may
find to be useful.

SUMMARY

 Assign a module code to whatever you want to build next. For example, “INV” for
inventory.
 Layout the list of functions that require permissions. For example, 1 for accessing the
inventory list, 2 for adding new items, 3 for editing items, etc…
 Add these permissions to the database, and assign which roles have the permissions.
 Build your library, extend the base library.
 Set the protected $modcode in your library.
 Run the checks before executing each get/add/edit/delete function.

LOGIN

Don’t have a login mechanism yet? Here is a guide on how to create one:

SOURCE CODE DOWNLOAD

Click here to download the source code in a zip file – I have released it under the MIT License,
so feel free to build on top of it if you want to.

CLOSING
WHAT’S NEXT?
Thank you for reading, and we have come to the end of this guide. I hope that it
has helped you to better manage access permissions in your project. If you have anything to
share with this guide, please feel free to comment below. Good luck, and happy coding!

Post navigation
← Previous Post
Next Post →

Leave a Comment

Your email address will not be published. Required fields are marked *

Type here..

Name*

Email*

Website

Site Links
 About Us
 Contact Us
 Disclosure
 Terms of Use
 Privacy Policy
 Credits
Follow Us
 Facebook
 Google Plus
 YouTube
 Pinterest

Recent Posts
 2 Ways to Create Responsive CSS Squares and Rectangles
 3 Simple Responsive Navigation Menu
 How to Create Simple CSS Responsive Logo
 3 Steps Simple Responsive Full Screen Images
 15 Awesome Gifts and Gadgets For Programmers (Under $50)

Search
Search for:

Copyright © 2019 Code Boxx. All rights reserved.


We use cookies to ensure that we give you the best experience on our website. If you continue to
use this site we will assume that you consent to it.OkPrivacy policy

Skip to content

 Learn
o
Basic HTML
o
Basic CSS
o
Basic Javascript
o
Responsive CSS
 Tips & Tutorials
o PHP
o Javascript
o HTML & CSS
o Others
 Projects
o Cart Boxx
o Invoicr
 Recommendations
 Search

3 Steps Simple PHP User Role Management


System
Share





INTRODUCTION
THE PERMISSIONS HEADACHE
Welcome to a tutorial on how to create a simple PHP User Role Management System. So you
have a project that needs to identify and restrict what each user is able to do – Creating a
permissions structure is often quite a grueling task, but I shall share my simple solution in this
guide. Read on!

I have included a zip file with all the source code at the end of this tutorial, so you don’t have to
copy-paste everything… Or if you just want the code and skip the tutorial.

CONFESSION
AN HONEST DISCLOSURE

Quick, hide your wallets! I am an affiliate partner of Google, eBay, Adobe, Bluehost, Clickbank,
and more. There are affiliate links and advertisements throughout this website. Whenever you
buy things from the evil links that I recommend, I will make a commission. Nah. These are just
things to keep the blog going, and allows me to give more good stuff to you guys - for free. So
thank you if you decide to pick up my recommendations!

NAVIGATION
TABLE OF CONTENTS

Prelude Step 1 Step 2


Overview & Assumptions The Database The Base Library

Step 3 Extra Closing


Add The Checks! Download & More What’s Next?

PRELUDE
OVERVIEW & ASSUMPTIONS

Before we dive into the code, let us start with an overview of the entire project, plus some
assumptions that I have made – So you know what to expect from this guide.
THE SYSTEM STRUCTURE

I am sure that everyone here already has an existing website, and it follows the “universal”
structure of:

 Database – Storing all your users’ data and stuff.


 Server-side Scripts – A set of library files and process handlers.
 Client-side Scripts – Front-end user interface.

Thus, I shall assume that you guys already have some sort of a user database, admin panel, and
login mechanism – We will not reinvent the wheel in this guide and come up with another user
login system plus admin interface. What we will focus on, are the database, the libraries, plus the
concepts of a user role/permission system.

We will not build any nice looking user interfaces in this guide, but touch more on the technical
changes you need to make on your existing system. Also, I shall assume that you guys are
already veteran code ninjas who are comfortable with PHP, HTML, CSS, Javascript, AJAX, and
SQL… That I will not need to explain the tiny boring details of “how HTML and CSS work”.

STEP 1
THE DATABASE

Let us now start with the foundations of the system, the database – Don’t worry if you have not
created a users database yet, I shall provide a complete working system here.

1A) THE TABLES


There are 4 tables involved in this project:

 Permissions – To keep track of actions that require permission. For example, accessing
the list of users, and creating new users.
 Roles – Names of the roles. For examples, administrators, editors, etc…
 Roles-Permissions – To specify which role has which permissions.
 Users -Your list of users and their roles.

1B) THE SQL

permissions.sql
-- [USER TABLE]
-- ! JUST ADD A ROLE_ID IF YOU HAVE AN EXISTING TABLE !
CREATE TABLE `users` (
`user_id` int(11) NOT NULL,
`user_email` varchar(255) NOT NULL,
`user_name` varchar(255) NOT NULL,
`user_password` varchar(255) NOT NULL,
`role_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `users`


ADD PRIMARY KEY (`user_id`),
ADD UNIQUE KEY `user_email` (`user_email`),
ADD KEY `user_name` (`user_name`);

ALTER TABLE `users`


MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT;

-- [PERMISSIONS TABLES]
CREATE TABLE `permissions` (
`perm_mod` varchar(5) NOT NULL,
`perm_id` int(11) NOT NULL,
`perm_desc` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `permissions`


ADD PRIMARY KEY (`perm_mod`,`perm_id`);

CREATE TABLE `roles` (


`role_id` int(11) NOT NULL,
`role_name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `roles`


ADD PRIMARY KEY (`role_id`),
ADD UNIQUE KEY `role_name` (`role_name`);

ALTER TABLE `roles`


MODIFY `role_id` int(11) NOT NULL AUTO_INCREMENT;

CREATE TABLE `roles_permissions` (


`role_id` int(11) NOT NULL,
`perm_mod` varchar(5) NOT NULL,
`perm_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `roles_permissions`


ADD PRIMARY KEY (`role_id`,`perm_mod`,`perm_id`);
Users
Field Description
user_id The user ID, auto-increment and primary key.
user_email User’s email. Set to unique to prevent duplicate registrations.
user_name The user’s name. Indexed, for fast searches.
user_password User password.
role_id Role of the user.

If you already have an existing users table, just add a role ID to it.

Permissions
Field Description
The module, an abbreviation code up to 5 characters. For example “USR” for users,
perm_mod
“INV” for inventory. Partial primary key.
perm_id Permissions ID, just a running number. Partial primary key.
perm_desc Permission description. For example, access inventory list, create a new user, etc…
Roles
Field Description
role_id Role ID, primary key and auto-increment.
role_name Name of the role. For example, an administrator.
Role Permissions
Field Description
role_id Role ID, partial primary key.
perm_mod Module code, partial primary key.
perm_id Permission ID, partial primary key.

That’s it for the tables, but please do remember to add more of your own permissions and roles.

1C) SAMPLE DATA

This is the set of dummy data that we will use as examples in this guide.
sample.sql
-- [DUMMY DATA]
-- USER PASSWORD IS 123456
INSERT INTO `users` (`user_id`, `user_email`, `user_name`, `user_password`,
`role_id`) VALUES
(1, 'john@doe.com', 'John Doe',
'$2y$10$EIPcGzgNnfpZM9gkm3GqiuNaGjZuJwdCggOVrwzJ6olNQqqRmCH5i', 1),
(2, 'jane@doe.com', 'Jane Doe',
'$2y$10$EIPcGzgNnfpZM9gkm3GqiuNaGjZuJwdCggOVrwzJ6olNQqqRmCH5i', 2);

INSERT INTO `permissions` (`perm_mod`, `perm_id`, `perm_desc`) VALUES


('USR', 1, 'Access users'),
('USR', 2, 'Create new users'),
('USR', 3, 'Update users'),
('USR', 4, 'Delete users');

INSERT INTO `roles` (`role_id`, `role_name`) VALUES


(1, 'Administrator'),
(2, 'Power User');

INSERT INTO `roles_permissions` (`role_id`, `perm_mod`, `perm_id`) VALUES


(1, 'USR', 1),
(1, 'USR', 2),
(1, 'USR', 3),
(1, 'USR', 4),
(2, 'USR', 1);

STEP 2
THE BASE LIBRARY

With the database foundations established, we shall now build the libraries for permissions
checking.

2A) THE CONFIG FILE

config.php
<?php
// MUTE NOTICES
error_reporting(E_ALL & ~E_NOTICE);
// DATABASE SETTINGS - CHANGE THESE TO YOUR OWN
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_CHARSET', 'utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
?>

If you have not already created a config file, it is time to do so. There is nothing much to it, just
remember to change the database settings to your own.

2B) THE BASE LIBRARY

lib-db.php
<?php
class Base {
private $pdo = null;
private $stmt = null;
public $error = "";
public $lastID = null;

function __construct() {
// __construct() : connect to the database
// PARAM : DB_HOST, DB_CHARSET, DB_NAME, DB_USER, DB_PASSWORD

// ATTEMPT CONNECT
try {
$str = "mysql:host=" . DB_HOST . ";charset=" . DB_CHARSET;
if (defined('DB_NAME')) { $str .= ";dbname=" . DB_NAME; }
$this->pdo = new PDO(
$str, DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
return true;
}

// ERROR - DO SOMETHING HERE


// THROW ERROR MESSAGE OR SOMETHING
catch (Exception $ex) {
print_r($ex);
die();
}
}

function __destruct() {
// __destruct() : close connection when done

if ($this->stmt !== null) { $this->stmt = null; }


if ($this->pdo !== null) { $this->pdo = null; }
}
function start() {
// start() : auto-commit off

$this->pdo->beginTransaction();
}

function end($commit=1) {
// end() : commit or roll back?

if ($commit) { $this->pdo->commit(); }
else { $this->pdo->rollBack(); }
}

function exec($sql, $data=null) {


// exec() : run insert, replace, update, delete query
// PARAM $sql : SQL query
// $data : array of data

try {
$this->stmt = $this->pdo->prepare($sql);
$this->stmt->execute($data);
$this->lastID = $this->pdo->lastInsertId();
} catch (Exception $ex) {
$this->error = $ex;
return false;
}
$this->stmt = null;
return true;
}

function fetch($sql, $cond=null, $key=null, $value=null) {


// fetch() : perform select query
// PARAM $sql : SQL query
// $cond : array of conditions
// $key : sort in this $key=>data order, optional
// $value : $key must be provided, sort in $key=>$value order

$result = false;
try {
$this->stmt = $this->pdo->prepare($sql);
$this->stmt->execute($cond);
if (isset($key)) {
$result = array();
if (isset($value)) {
while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) {
$result[$row[$key]] = $row[$value];
}
} else {
while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) {
$result[$row[$key]] = $row;
}
}
} else {
$result = $this->stmt->fetchAll();
}
} catch (Exception $ex) {
$this->error = $ex;
return false;
}
$this->stmt = null;
return $result;
}

function check($perm, $mod="") {


// check() : checks if user has sufficient access rights
// PARAM $perm : permission ID
// $mod : module code
// !! USER MUST BE SIGNED IN FIRST !!

// INIT
$pass = true;
if ($mod=="") { $mod = $this->modcode; }

// NOT SIGNED IN
// OR USER DOES NOT HAVE PERMISSION TO ENTIRE MODULE
if (!is_array($_SESSION['user']['perm'][$mod])) { $pass = false; }

// CHECK SPECIFIC PERMISSION


if (!in_array($perm, $_SESSION['user']['perm'][$mod])) { $pass = false; }

// RETURN ACCESS CHECK


if (!$pass) { $this->error = "You do not have sufficient access rights.";
}
return $pass;
}
}
?>
Function Description
__construct The constructor, automatically connects to the database when the object is created.
The destructor, automatically disconnects from the database when the object is
__destructor
destroyed.
start Auto-commit off. Used for multiple queries, in conjunction with end.
To commit or rollback the queries. Used for multiple queries, in conjunction with
end
start.
exec Executes insert, replace, update, and delete queries.
fetch Executes select query.
check Checks if the user has access to the given module/action.

Yep, this is actually a database library that we will be building the rest of the system upon. The
key function that you have to take note here is check.
STEP 3
ADDING CHECKS

With the database and base library, all that is left to do to complete the puzzle is to integrate the
actual checks.

3A) CHECKS IN LIBRARY FILES

Just how the heck do we use the base library and do the checks? Let us start by creating a users
library as an example.

lib-users.php
<?php
class Users extends Base {
protected $modcode = "USR";
function in($email, $password) {
// in() : sign in given user

// Get user
$entry = $this->fetch(
"SELECT * FROM `users` LEFT JOIN `roles` USING (`role_id`) WHERE
`user_email`=?",
[$email]
);
if (count($entry)==0) { return false; }
else {
// Verify password
$entry = $entry[0];
if (password_verify($password, $entry['user_password'])) {
$_SESSION['user'] = [
"user_id" => $entry['user_id'],
"role_id" => $entry['role_id'],
"role_name" => $entry['role_name'],
"user_email" => $entry['user_email'],
"user_name" => $entry['user_name']
];
// Get permissions
$entry = $this->fetch(
"SELECT * FROM `roles_permissions` WHERE `role_id`=?",
[$entry['role_id']]
);
if (is_array($entry)) {
$_SESSION['user']['perm'] = [];
foreach ($entry as $e) {
if (!is_array($_SESSION['user']['perm'][$e['perm_mod']])) {
$_SESSION['user']['perm'][$e['perm_mod']] = [];
}
$_SESSION['user']['perm'][$e['perm_mod']][] = $e['perm_id'];
}
}
} else { return false; }
}
return true;
}

function get($id) {
// get() : get user
// PARAM $id : user ID or email

// ACCESS CHECK
if (!$this->check(1)) { return false; }

// FETCH
$sql = sprintf("SELECT * FROM `users` LEFT JOIN `roles` USING (`role_id`)
WHERE `user_%s`=?",
is_numeric($id) ? "id" : "email"
);
$entry = $this->fetch($sql, [$id]);
return count($entry)==0 ? false : $entry[0] ;
}

function add($email, $name, $password, $role) {


// add() : add a new user
// PARAM $email : email address
// $name : user name
// $password : plain text password
// $role : role ID

// ACCESS CHECK
if (!$this->check(2)) { return false; }

// INSERT
return $this->exec(
"INSERT INTO `users` (`user_email`, `user_name`, `user_password`,
`role_id`) VALUES (?, ?, ?, ?)",
[$email, $name, password_hash($password, PASSWORD_DEFAULT), $role]
);
}

function edit($email, $name, $password, $role, $id) {


// edit() : update an existing user
// PARAM $email : email address
// $name : user name
// $password : plain text password
// $role : role ID
// $id : user ID

// ACCESS CHECK
if (!$this->check(3)) { return false; }
// UPDATE
return $this->exec(
"UPDATE `users` SET `user_email`=?, `user_name`=?, `user_password`=?,
`role_id`=? WHERE `user_id`=?",
[$email, $name, password_hash($password, PASSWORD_DEFAULT), $role, $id]
);
}

function delete($id) {
// delete() : delete user
// PARAM $id : user ID

// ACCESS CHECK
if (!$this->check(4)) { return false; }

// DELETE
return $this->exec(
"DELETE FROM `users` WHERE `user_id`=?",
[$id]
);
}
}
?>
Function Description
Sign in the given user – Will populate$_SESSION['user'] with the user and access
in
permissions. Make sure that the session is started before calling this function!
get Get the given user ID or email.
add Add a new user.
edit Update an existing user.
delete Delete the existing user.

Let us now follow up with how the permissions checking work:

1. This users library is a child of the base class. Meaning, it inherits all the database and
check functions.
2. The users library is given the module code of “USR” with protected $modcode =
"USR";
3. Before running the functions get, add, edit, and delete – There will be an access
permission check.
4. The check function will simply match against the user session to see if the user has
access rights for the given module code and permission ID.

3B) SET THE PERMISSIONS IN THE SESSION!

So yep, the key is to first put the access permissions into session upon login – You can recycle
my user library and login function in your own project if you wish.
eg-1-login.php
<?php
// INIT
session_start();
require "config.php";
require "lib-base.php";
require "lib-users.php";

// LOGIN
echo $libUsr->in("john@doe.com", "123456") ? "OK" : $libUsr->error ;
print_r($_SESSION);
?>

3C) EVERYTHING SHOULD AUTOMATICALLY FALL IN PLACE

Once those are done, everything should pretty much automatically fall in place. For example, the
library functions will only run when the user has sufficient access rights:

eg-2-ajax.php
<?php
// INIT
session_start();
require "config.php";
require "lib-base.php";
require "lib-users.php";

// ADD NEW USER


echo $libUsr->add($_POST['email'], $_POST['name'], $_POST['password'],
$_POST['role'])
? "OK"
: $libUsr->error ;
?>

Or you can directly use the check function to restrict access to certain pages:

eg-3-page.php
<?php
// INIT
session_start();
require "config.php";
require "lib-base.php";
require "lib-users.php";

// CHECK ACCESS TO PAGE


if (!$libUsr->check(1)) {
die("You do not have access to this page.");
} ?>
<!DOCTYPE html>
<html>
<body>Yes, you can access the users management page</body>
</html>

EXTRA
DOWNLOAD & MORE

That’s it for all the code, and here is the download as promised plus a small extra that you may
find to be useful.

SUMMARY

 Assign a module code to whatever you want to build next. For example, “INV” for
inventory.
 Layout the list of functions that require permissions. For example, 1 for accessing the
inventory list, 2 for adding new items, 3 for editing items, etc…
 Add these permissions to the database, and assign which roles have the permissions.
 Build your library, extend the base library.
 Set the protected $modcode in your library.
 Run the checks before executing each get/add/edit/delete function.

LOGIN

Don’t have a login mechanism yet? Here is a guide on how to create one:

SOURCE CODE DOWNLOAD

Click here to download the source code in a zip file – I have released it under the MIT License,
so feel free to build on top of it if you want to.
CLOSING
WHAT’S NEXT?

Thank you for reading, and we have come to the end of this guide. I hope that it
has helped you to better manage access permissions in your project. If you have anything to
share with this guide, please feel free to comment below. Good luck, and happy coding!

Post navigation
← Previous Post
Next Post →

Leave a Comment

Your email address will not be published. Required fields are marked *

Type here..

Name*

Email*

Website

Site Links
 About Us
 Contact Us
 Disclosure
 Terms of Use
 Privacy Policy
 Credits

Follow Us
 Facebook
 Google Plus
 YouTube
 Pinterest

Recent Posts
 2 Ways to Create Responsive CSS Squares and Rectangles
 3 Simple Responsive Navigation Menu
 How to Create Simple CSS Responsive Logo
 3 Steps Simple Responsive Full Screen Images
 15 Awesome Gifts and Gadgets For Programmers (Under $50)

Search
Search for:

Copyright © 2019 Code Boxx. All rights reserved.


We use cookies to ensure that we give you the best experience on our website. If you continue to
use this site we will assume that you consent to it.OkPrivacy policy
Skip to content

 Learn
o
Basic HTML
o
Basic CSS
o
Basic Javascript
o
Responsive CSS
 Tips & Tutorials
o PHP
o Javascript
o HTML & CSS
o Others
 Projects
o Cart Boxx
o Invoicr
 Recommendations
 Search

3 Steps Simple PHP Order Form (Script


Download Included)
Share





INTRODUCTION
A SIMPLE LIFE
Welcome to a tutorial on how to create a simple PHP order form – That will either be sent to
your email and/or kept in a database. Yep, there are a ton of different shopping carts out there,
but maybe they are too complicated and you don’t like it. So in this guide, we will walk you
through how to create a simple order form, step-by-step. Read on!

I have included a zip file with all the source code at the end of this tutorial, so you don’t have to
copy-paste everything… Or if you just want the code and skip the tutorial.

CONFESSION
AN HONEST DISCLOSURE
Quick, hide your wallets! I am an affiliate partner of Google, eBay, Adobe, Bluehost, Clickbank,
and more. There are affiliate links and advertisements throughout this website. Whenever you
buy things from the evil links that I recommend, I will make a commission. Nah. These are just
things to keep the blog going, and allows me to give more good stuff to you guys - for free. So
thank you if you decide to pick up my recommendations!

NAVIGATION
TABLE OF CONTENTS

Prelude Step 1 Step 2


Overview & Assumptions The Order Form Send Email

Step 3 Extra Closing


Database Orders Download & more What’s Next?

PRELUDE
OVERVIEW & ASSUMPTIONS
Before we dive into the code, here is a small section on the overview of the process, and some
assumptions that I have made – So that you know what to expect from this simple example and
tutorial.

PROCESS OVERVIEW

 The users will land on an order form page, where they fill in their details.
 Upon submitting the order form, the server will send out an email to a specified email
address with the order details.
 Optionally, the order will be saved in a database – This is where things get not-so-simple.
 You will also need an admin page to pull out and show orders from the database.

So I shall assume here that you guys already have a working webpage/blog/e-commerce website
– I will only provide code snippets for the database, should you want to build one. I will not go
into building an entire login mechanism in this guide, as that will turn it into a “not easy”

tutorial. But I will still provide links to my other guides if you want to build a users system
and admin login.
STEP 1
THE ORDER FORM

Let us get started with the easiest component of this project, the order form… Which is nothing
more than just a few simple lines of HTML and CSS.

THE HTML

1-form.html
<!DOCTYPE html>
<html>
<head>
<title>Order Form Example</title>
<link href="theme.css" rel="stylesheet">
</head>
<body>
<h1>Order Form</h1>
<form method="post" target="_blank" action="2-email.php">
<label for="name">Name:</label>
<input type="text" name="name" required value="John Doe"/>
<label for="email">Email:</label>
<input type="email" name="email" required value="john@doe.com"/>
<label for="tel">Telephone:</label>
<input type="text" name="tel" required value="123-456-789"/>
<label for="qty">Quantity Needed:</label>
<input type="number" name="qty" required value="1"/>
<label for="notes">Additional Notes (if any):</label>
<textarea name="notes"></textarea>
<br>
<input type="submit" value="Place Order"/>
</form>
</body>
</html>

Please feel free to modify this form – Capture the information that you require for your orders.

THE CSS

theme.css
body, html, input, textarea {
font-family: arial;
}
h1 {
padding: 0;
margin: 10px 0;
}
label {
display: block;
margin: 5px 0;
}
input[type=text], input[type=email], input[type=number], textarea {
padding: 5px;
display: block;
resize: none;
min-width: 300px;
}
input[type=submit] {
background: #AA2020;
color: #fff;
border: 0;
padding: 10px;
font-size: 1em;
font-weight: bold;
}

This is just some simple CSS and cosmetics… just so that the form will not look butt naked. Feel
free to change this to fit your site, or don’t use it at all.

STEP 2
SEND EMAIL

Now that you have the order form, the next step is to just capture the data and send it out in an
email.

THE EMAIL PROCESSOR


2-email.php
<?php
/* [FORMULATE EMAIL] */
$to = "YOUR@EMAIL.COM"; // SET YOUR EMAIL!
$subject = "Order Received";
$message = "<html><body>";
$message .= "<p>An order has been receieved on " . date("j M Y H:i:s") .
"</p>";
$message .= "<table>";
foreach ($_POST as $k=>$v) {
$message .= "<tr><td><strong>$k:</strong></td><td>$v</td></tr>";
}
$message .= "</table></body></html>";
$headers = [
'MIME-Version: 1.0',
'Content-type: text/html; charset=utf-8',
'From: sys@your-site.com' // CHANGE THIS IF YOU WANT
];
$headers = implode("\r\n", $headers);

// SEND!
$pass = @mail($to, $subject, $message, $headers);
?>
<!DOCTYPE html>
<html>
<head>
<title>Order Form Example</title>
<link href="theme.css" rel="stylesheet">
</head>
<body>
<h1><?=$pass ? "ORDER RECEIEVED" : "OPPS! AN ERROR HAS OCCURRED!"?></h1>
<p>
<?=$pass ? "We have receieved your own and will get back to you ASAP."
: "Please refresh the page and try again."?>
</p>
</body>
</html>

This script should be pretty straightforward – It compiles all the order information and sends it
out via email, that’s all.

 Remember to change to the email address above!


 You might also want to give this page some more cosmetics…

STEP 3
DATABASE ORDER
Actually, the above 2 steps will do the work just fine. But there are times where emails can land
in the spam or junk folder… A database to store the orders is still the wiser and safer way.

THE DATABASE SQL

orders.sql
CREATE TABLE `orders` (
`order_id` int(11) NOT NULL,
`dop` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`tel` varchar(14) NOT NULL,
`qty` int(5) NOT NULL,
`notes` text
) ENGINE=InnoDB DEFAULT CHARSET=utf

ALTER TABLE `orders`


ADD PRIMARY KEY (`order_id`),
ADD KEY `dop` (`dop`);

ALTER TABLE `orders`


MODIFY `order_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

Let us first create a database table. This is an exact replica of the fields in the HTML order form
– Feel free to add/remove fields that you need.

P.S. For the total beginners, you can easily manage your database with a free manager such as
phpMyAdmin; You can import the above SQL easily with just a few clicks.

CONFIG FILE

config.php
<?php
// DATABASE SETTINGS - CHANGE THESE TO YOUR OWN
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_CHARSET', 'utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
?>

To make life easier, let us create a config file – Remember to change the database settings to
your own.

EMAIL + DATABASE

2-email-db.php
<?php
/* [FORMULATE EMAIL] */
$to = "YOUR@EMAIL.COM"; // SET YOUR EMAIL!
$subject = "Order Received";
$message = "<html><body>";
$message .= "<p>An order has been receieved on " . date("j M Y H:i:s") .
"</p>";
$message .= "<table>";
foreach ($_POST as $k=>$v) {
$message .= "<tr><td><strong>$k:</strong></td><td>$v</td></tr>";
}
$message .= "</table></body></html>";
$headers = [
'MIME-Version: 1.0',
'Content-type: text/html; charset=utf-8',
'From: sys@your-site.com' // CHANGE THIS IF YOU WANT
];
$headers = implode("\r\n", $headers);

// SEND!
$pass = @mail($to, $subject, $message, $headers);

/* [SAVE TO DATABASE] */
// Connect to database
if ($pass) {
require "config.php";
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" .
DB_CHARSET,
DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
}
catch (Exception $ex) {
$pass = false;
}
}
// Save entry
if ($pass) {
try {
$sql = "INSERT INTO `orders` (`name`, `email`, `tel`, `qty`, `notes`)
VALUES (?, ?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([
$_POST['name'], $_POST['email'], $_POST['tel'],
$_POST['qty'], $_POST['notes']
]);
} catch (Exception $ex) {
$pass = false;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Order Form Example</title>
<link href="theme.css" rel="stylesheet">
</head>
<body>
<h1><?=$pass ? "ORDER RECEIEVED" : "OPPS! AN ERROR HAS OCCURRED!"?></h1>
<p>
<?=$pass ? "We have receieved your own and will get back to you ASAP."
: "Please refresh the page and try again."?>
</p>
</body>
</html>

With those foundations, we can now safely modify the script to save to the database after
sending out the email.

ADMIN PAGE

That’s it, you now have a fully functioning system – If you are lazy, you can just use
phpMyAdmin to access the orders in the database. If not, you can create another simple admin
page that pulls out all the recent orders:

3-admin.php
<?php
// Connect to database
require "config.php";
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" .
DB_CHARSET,
DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
}
catch (Exception $ex) {
die("ERROR CONNECTING TO DATABASE");
}

// Get orders
$sql = "SELECT * FROM `orders` ORDER BY `dop` DESC LIMIT 30";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$orders = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html>
<head>
<title>Order Form Admin Example</title>
<link href="theme.css" rel="stylesheet">
</head>
<body>
<h1>Orders</h1>
<table>
<?php
if (count($orders)>0) {
foreach ($orders as $o) {
echo "<tr><td>";
foreach ($o as $k=>$v) {
echo "<strong>$k</strong> - $v <br>";
}
echo "</td></tr>";
}
} else {
echo "<tr><td>No orders found.</td></tr>";
}
?>
</table>
</body>
</html>

Reminder – You might want to put this page on an intranet, away from the public, or protect this
with a login.

EXTRA
DOWNLOAD & MORE
That’s it for all the code, and here is the download link as promised, plus some small extras that
may be useful to you.

CAPTCHA

An open order form is just waiting for spammers to open fire upon… You might want to add a
CAPTCHA to your order form and protect it against spam.

LOGIN

For you guys who want to create your own login system, here is my other guide.

SOURCE CODE DOWNLOAD

Click here to download the source code in a zip file – I have released it under the MIT License,
so feel free to build on top of it if you want to.

CLOSING
WHAT NEXT?

Thank you for reading, and we have come to the end of this short tutorial. I
hope it has helped you to create a better website. If you anything to share with this guide, please
feel free to comment below. Good luck and happy coding!

Post navigation
← Previous Post
Next Post →
Leave a Comment

Your email address will not be published. Required fields are marked *

Type here..

Name*

Email*

Website

Site Links
 About Us
 Contact Us
 Disclosure
 Terms of Use
 Privacy Policy
 Credits

Follow Us
 Facebook
 Google Plus
 YouTube
 Pinterest

Recent Posts
 2 Ways to Create Responsive CSS Squares and Rectangles
 3 Simple Responsive Navigation Menu
 How to Create Simple CSS Responsive Logo
 3 Steps Simple Responsive Full Screen Images
 15 Awesome Gifts and Gadgets For Programmers (Under $50)
Search
Search for:

Copyright © 2019 Code Boxx. All rights reserved.


We use cookies to ensure that we give you the best experience on our website. If you continue to
use this site we will assume that you consent to it.OkPrivacy policy

S-ar putea să vă placă și