Simple PHP Admin Panel (Free Download)

Welcome to a tutorial on how to create a simple PHP admin panel. Since you are reading this, I will assume that you are interested in “powering up” your existing project and want to build an administrative component to it. So here is a sharing of my own – All done in pure HTML, CSS, Javascript, and PHP. No third-party frameworks. Read on!

 

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

Here is the download link to the example code, so you don’t have to copy-paste everything.

 

EXAMPLE CODE DOWNLOAD

Source code on GitHub Gist

Just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

 

PHP MYSQL ADMIN PANEL

All right, let us now get into the details of how to create a simple admin panel with PHP and MySQL.

 

TUTORIAL VIDEO

 

PART 1) USER DATABASE

1-users.sql
-- (A) USERS TABLE
CREATE TABLE `users` (
  `user_id` bigint(20) NOT NULL,
  `user_email` varchar(255) NOT NULL,
  `user_name` varchar(255) NOT NULL,
  `user_password` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

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` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

-- (B) DEFAULT USER
-- EMAIL: JOY@DOE.COM | PASSWORD: 123456
INSERT INTO `users` (`user_id`, `user_email`, `user_name`, `user_password`) VALUES
(1, 'joy@doe.com', 'Joy Doe', '$2y$10$vZJy7y4uqQQTRN3zdi2RE.5ZJJzGEEPnzEjFXm4nEOx023XQ2Qe..');

First, let us begin by dealing with the obvious – A database to hold the admin users.

  • user_id Primary key and auto-increment.
  • user_email User email, unique to prevent duplicates.
  • user_name User name.
  • user_password The user’s password.

 

 

PART 2) PHP ADMIN LIBRARY

2-lib-admin.php
<?php
class Admin {
  // (A) CONSTRUCTOR - CONNECT TO DATABASE
  private $pdo = null;
  private $stmt = null;
  public $error = "";
  function __construct () {
    $this->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
    ]);
  }

  // (B) DESTRUCTOR - CLOSE CONNECTION
  function __destruct () {
    if ($this->stmt !== null) { $this->stmt = null; }
    if ($this->pdo !== null) { $this->pdo = null; }
  }

  // (C) HELPER FUNCTION - RUN SQL QUERY
  function query ($sql, $data=null) : void {
    $this->stmt = $this->pdo->prepare($sql);
    $this->stmt->execute($data);
  }

  // (D) GET USER BY ID OR EMAIL
  function get ($id) {
    $this->query(sprintf("SELECT * FROM `users` WHERE `%s`=?",
      is_numeric($id) ? "user_id" : "user_email"
    ), [$id]);
    return $this->stmt->fetch();
  }

  // (E) SAVE USER
  function save ($name, $email, $password, $id=null) {
    // (E1) SQL & DATA
    $sql = $id==null
      ? "INSERT INTO `users` (`user_name`, `user_email`, `user_password`) VALUES (?,?,?)"
      : "UPDATE `users` SET `user_name`=?, `user_email`=?, `user_password`=? WHERE `user_id`=?" ;
    $data = [$name, $email, password_hash($password, PASSWORD_DEFAULT)];
    if ($id!=null) { $data[] = $id; }

    // (E2) RUN SQL
    $this->query($sql, $data);
    return true;
  }

  // (F) VERIFICATION
  function verify ($email, $password) {
    // (F1) GET USER
    $user = $this->get($email);
    $pass = is_array($user);

    // (F2) CHECK PASSWORD
    if ($pass) { $pass = password_verify($password, $user["user_password"]); }

    // (F3) REGISTER MEMBER INTO SESSION
    if ($pass) {
      foreach ($user as $k=>$v) { $_SESSION["admin"][$k] = $v; }
      unset($_SESSION["admin"]["user_password"]);
    }

    // (F4) RESULT
    if (!$pass) { $this->error = "Invalid email/password"; }
    return $pass;
  }
}

// (G) DATABASE SETTINGS - CHANGE TO YOUR OWN
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8mb4");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// (H) START!
session_start();
$_ADM = new Admin();

This PHP core and database library is here to help you guys develop a little faster. It may look confusing at first, but keep calm and look closely.

  • (A, B, H) When $_ADM = new Admin() is created, the constructor will connect to the database. The destructor closes the connection.
  • (C) query() A helper function to execute an SQL query.
  • (D to F) The actual admin functions.
    • get() Get user by ID or email.
    • save() Add or update a user.
    • verify() Verify the given email and password. Register the user into $_SESSION["admin"].
  • (G) The database settings, remember to change them to your own.
  • (H) Start the “engine”.

 

 

PART 3) LOGIN PAGE

3a-login.php
<?php
// (A) LOAD LIBRARY
require "2-lib-admin.php";
 
// (B) CHECK LOGIN CREDENTIALS
if (count($_POST)!=0) {
  $_ADM->verify($_POST["email"], $_POST["password"]);
}
 
// (C) REDIRECT IF SIGNED IN
if (isset($_SESSION["admin"])) {
  header("Location: 5-protected.php");
  exit();
} ?>
 
<!-- (D) LOGIN FORM -->
<?php
if ($_ADM->error!="") { echo "<div class='error'>".$_ADM->error."</div>"; }
?>
<form method="post">
  <h1>ADMIN LOGIN</h1>
  <label>Email</label>
  <input type="email" name="email" required>
  <label>Password</label>
  <input type="password" name="password" required>
  <input type="submit" value="Login">
</form>

It will be easier to study this login page from the bottom up.

  • (D) A good old HTML login form.
  • (A & B) On submission, we use the library to process the login request.
  • (C) On successful login, we redirect the user to the “main admin page”; Any users who are already signed in will also be redirected.

 

PART 4) ADMIN HTML TEMPLATE

4A) TOP HALF

4a-top.php
<?php
// (A) LOAD LIBRARY
require "2-lib-admin.php";

// (B) LOGOUT
if (isset($_POST["logout"])) { unset($_SESSION["admin"]); }

// (C) REDIRECT IF NOT SIGNED IN
if (!isset($_SESSION["admin"])) {
  header("Location: 3a-login.php");
  exit();
} ?>

<!-- (D) SIDEBAR -->
<div id="pgside">
  <!-- (D1) BRANDING OR USER -->
  <form id="pguser" method="post" onclick="if(confirm('Sign Off?')){this.submit();}">
    <input type="hidden" name="logout" value="1">
    <img src="potato.png" id="pguserimg">
    <div class="txt">
      <div id="pgusername"><?=$_SESSION["admin"]["user_name"]?></div>
      <div id="pguseracct">account | logoff</div>
    </div>
  </form>

  <!-- (D2) MENU ITEMS -->
  <a href="#" class="current">
    <i class="ico">&#9733;</i>
    <i class="txt">Section A</i>
  </a>
  <a href="#">
    <i class="ico">&#9728;</i>
    <i class="txt">Section B</i>
  </a>
  <a href="#">
    <i class="ico">&#9737;</i>
    <i class="txt">Section C</i>
  </a>
</div>
 
<!-- (E) MAIN -->
<main id="pgmain">

 

 

4B) BOTTOM HALF

4b-bottom.php
</main>

 

4C) A QUICK WALKTHROUGH

Once again, this looks complicated. But look closely, there are only 2 main sections:

  • (D) <div id="pgside"> The sidebar.
    • (D1) <form id="pguser"> The current user and hidden form for logout.
    • (D2) Insert your menu items here.
  • (E) <main id="pgmain"> Main content area.

As for how the logout works, it is very similar to the login page:

  • (B) When <form id="pguser"> is submitted, this will clear out $_SESSION["admin"].
  • (C) The user will be redirected back to the login page; All users that are not signed in will be redirected to the login page.

 

PART 5) PROTECTED ADMIN PAGES

5-protected.php
<?php require "4a-top.php"; ?>
Your dashboard here.
<?php require "4b-bottom.php"; ?>

That’s about it for everything, to create a protected admin page:

  • Simply require "4a-top.php" at the top, and require "4b-bottom.php" at the bottom.
  • Sandwich your contents in between.

 

 

EXTRAS

That’s all for the tutorial, and here are a few small extras and links that may be useful to you.

 

SLIGHTLY BETTER SECURITY

This admin panel is made for simplicity and does not have the best security… I will recommend doing the following at the very least:

  • Create a new lib folder.
  • For Apache users, create a lib/.htaccess file with one line – Deny from all. Users can no longer access the files in lib/ through http://, but PHP can still read them.
  • IIS and NGINX users – Create your own “translated .htaccess“.
  • Move 2-lib-admin.php, 4a-top.php, 4b-bottom.php into lib.
  • Of course, update the file paths in your scripts accordingly.
  • Remember to delete 1-users.sql.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end of this tutorial. I hope that it has helped speed up your project development, and if you have anything to share with this guide, please feel free to comment below. Good luck and happy coding!

23 thoughts on “Simple PHP Admin Panel (Free Download)”

  1. I have an extra row in my sql called rights, this is to check whether a user is an admin or not with 0 being no and 1 being yes, how would i make it so a user can only login if rights=1?

    1. Very simple. Just modify ajax-session.php, case "in", add another line of check.

      $pass = is_array($user);
      if ($pass) { $pass = $user['rights'] == 1; }

    1. Check that you have at least PHP 5.5 on the server – That is required to make password_hash() and password_verify() work. If it still fails, write a simple script to call the edit(EMAIL, NAME, PASSWORD, ID) function to update the user/password.

  2. Great!
    but though, I downloaded the zip file of this admin tutorial, when I click the login btn this is all I get.
    Invalid user/password

    Please how do I make this work?

    1. Got it – Updated the zip file a little. That is probably a “false alarm”, and an AJAX error instead. Change “ajax-session.php” to the absolute URL in login.php, line 13 if you are still getting the same error.

Leave a Comment

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