How to set up a login session through PHP, MySQL and HTML

I’m trying to create an authentication system in my CRUD application, but I can’t get the username to display on the index page.

Here is the code I have:

<?php

require_once "api/dbconnect.php";

session_start();

?>

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Cabarrus County Republican Party | Member Database</title>

  <!-- Custom fonts for this template -->
  <link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template -->
  <link href="css/sb-admin-2.min.css" rel="stylesheet">

  <!-- Custom styles for this page -->
  <link href="vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">

</head>

<body id="page-top">

  <!-- Page Wrapper -->
  <div id="wrapper">

    <!-- Sidebar -->
    <ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">

      <!-- Sidebar - Brand -->
      <a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
        <!--<div class="sidebar-brand-icon rotate-n-15">
          <i class="fas fa-laugh-wink"></i>
        </div> -->
        <div class="sidebar-brand-text mx-3"><img src="img/republican_logo.png" width = "50" height="50">&nbsp;&nbsp;CCRP</div>
      </a>

      <!-- Divider -->
      <hr class="sidebar-divider my-0">

      <!-- Nav Item - Dashboard -->
      <li class="nav-item active">
        <a class="nav-link" href="index.html">
          <i class="fas fa-fw fa-table"></i>
          <span>Database</span></a>
      </li>

      <!-- Divider -->
      <hr class="sidebar-divider">

      <!-- Heading -->
      <div class="sidebar-heading">
        User Interface
      </div>

      <!-- Nav Item - Pages Collapse Menu -->
      <li class="nav-item">
        <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true" aria-controls="collapsePages">
          <i class="fas fa-fw fa-tachometer-alt"></i>
          <span>Menu</span>
        </a>
        <div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
          <div class="bg-white py-2 collapse-inner rounded">
            <h6 class="collapse-header">User Interface</h6>
            <a class="collapse-item" href="create.html">Add New Members</a>
			<a class="collapse-item" href="#">Email <small>(beta)</small></a>
			<a class="collapse-item" href="#">Mass Email <small>(beta)</small></a>		  	
            <!-- <h6 class="collapse-header">User Account</h6>
            <a class="collapse-item" href="login.html">Login</a>
            <a class="collapse-item" href="register.html">Register</a>
            <a class="collapse-item" href="forgot-password.html">Forgot Password</a> -->
            <div class="collapse-divider"></div>
            <!-- <a class="collapse-item" href="blank.html">Blank Page</a> -->
          </div>
        </div>
      </li>

      <!-- Divider -->
      <hr class="sidebar-divider d-none d-md-block">

      <!-- Sidebar Toggler (Sidebar) -->
      <div class="text-center d-none d-md-inline">
        <button class="rounded-circle border-0" id="sidebarToggle"></button>
      </div>

    </ul>
    <!-- End of Sidebar -->

    <!-- Content Wrapper -->
    <div id="content-wrapper" class="d-flex flex-column">

      <!-- Main Content -->
      <div id="content">

        <!-- Topbar -->
        <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">

          <!-- Sidebar Toggle (Topbar) -->
          <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
            <i class="fa fa-bars"></i>
          </button>

          <!-- Topbar Search -->
          <!-- <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
            <div class="input-group">
              <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
              <div class="input-group-append">
                <button class="btn btn-primary" type="button">
                  <i class="fas fa-search fa-sm"></i>
                </button>
              </div>
            </div>
          </form> -->

          <!-- Topbar Navbar -->
          <ul class="navbar-nav ml-auto">

            <!-- Nav Item - Search Dropdown (Visible Only XS) -->
            <!-- <li class="nav-item dropdown no-arrow d-sm-none">
              <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="fas fa-search fa-fw"></i>
              </a> -->
              <!-- Dropdown - Messages -->
              <!-- <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">
                <form class="form-inline mr-auto w-100 navbar-search">
                  <div class="input-group">
                    <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
                    <div class="input-group-append">
                      <button class="btn btn-primary" type="button">
                        <i class="fas fa-search fa-sm"></i>
                      </button>
                    </div>
                  </div>
                </form>
              </div>
            </li> -_>

            <!-- <div class="topbar-divider d-none d-sm-block"></div> -->

            <!-- Nav Item - User Information -->
            <li class="nav-item dropdown no-arrow">
              <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <span class="mr-2 d-none d-lg-inline text-gray-600 small">Welcome, <?php echo $_SESSION["first_name"]; ?>!</span>
                <img class="img-profile rounded-circle" src="https://source.unsplash.com/QAB-WJcbgJk/60x60">
              </a>
              <!-- Dropdown - User Information -->
              <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
                <a class="dropdown-item" href="#">
                  <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
                  Profile
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
                  Settings
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
                  Activity Log
                </a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
                  <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
                  Logout
                </a>
              </div>
            </li>

          </ul>

        </nav>
        <!-- End of Topbar -->

        <!-- Begin Page Content -->
        <div class="container-fluid">

          <!-- Page Heading -->
          <h1 class="h3 mb-2 text-gray-800">Members List</h1>
          <!-- <p class="mb-4">DataTables is a third party plugin that is used to generate the demo table below. For more information about DataTables, please visit the <a target="_blank" href="https://datatables.net">official DataTables documentation</a>.</p> -->

          <!-- DataTables Example -->
          <div class="card shadow mb-4">
            <div class="card-header py-3">
              <h6 class="m-0 font-weight-bold text-primary">Cabarrus County Republican Party </h6>
            </div>
            <div class="card-body">
              <div class="table-responsive">
                <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
                  <thead>
                    <tr>
					  <th>ID</th>
                      <th>Name</th>
                      <th>Residential Address</th>
                      <th>Mailing Address</th>
                      <th>Precinct</th>
                      <th>Age</th>
                      <th>Ethnicity</th>
					  <th>Gender</th>
					  <th>Party</th>
					  <th>Race</th>
					  <th>Phone Number</th>
                    </tr>
                  </thead>
                  <tfoot>
                    <tr>
					  <th>ID</th>
                      <th>Name</th>
                      <th>Residential Address</th>
                      <th>Mailing Address</th>
                      <th>Precinct</th>
                      <th>Age</th>
                      <th>Ethnicity</th>
					  <th>Gender</th>
					  <th>Party</th>
					  <th>Race</th>
					  <th>Phone Number</th>
                    </tr>
                  </tfoot>
                </table>
              </div>
            </div>
          </div>

        </div>
        <!-- /.container-fluid -->

      </div>
      <!-- End of Main Content -->

      <!-- Footer -->
      <footer class="sticky-footer bg-white">
        <div class="container my-auto">
          <div class="copyright text-center my-auto">
            <span>Copyright &copy; <a href="https://cascosigns.com">Casco Signs Inc.</a> 2019</span>
          </div>
        </div>
      </footer>
      <!-- End of Footer -->

    </div>
    <!-- End of Content Wrapper -->

  </div>
  <!-- End of Page Wrapper -->

  <!-- Scroll to Top Button-->
  <a class="scroll-to-top rounded" href="#page-top">
    <i class="fas fa-angle-up"></i>
  </a>

  <!-- Logout Modal-->
  <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
          <button class="close" type="button" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">You are logging out of the CCRP Database.</div>
        <div class="modal-footer">
          <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
          <a class="btn btn-primary" href="logout.php">Logout</a>
        </div>
      </div>
    </div>
  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="vendor/jquery/jquery.min.js"></script>
  <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="js/sb-admin-2.min.js"></script>

  <!-- Page level plugins -->
  <script src="vendor/datatables/jquery.dataTables.min.js"></script>
  <script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>

  <!-- Page level custom scripts -->
  <script src="js/datatables.js"></script>

</body>

</html>

I have an undefined index error on the index page:
Notice: Undefined index: first_name in C:\xampp\htdocs\ccrp\index.php on line 155

But i don’t know where or how to define it. I tried identifing it on the homepage, but I removed the code because it isn’t working. What do I do?

Where is the code that does anything to login a user or retrieve the DB data?

Put the code back in, so that someone can help you figure out why it isn’t working, maybe?

I was about to ask which is line 155 in your complete code, but if you’ve removed it, it probably isn’t there. It’s an idea in these cases to narrow down the code to a bit either side of the problem area, rather than post the whole lot.

The message suggests that you are referencing an array element that does not exist, so you need to look back and see where it should have come from, and why it might not have done. If it’s a session variable, for example, was it set properly in the originating page? If it’s being retrieved from the database, has the query worked?

1 Like

That’s what I’m trying to build. require_once "api/dbconnect.php is the code that connects to the DB. The table is called admins and I have 1 user in the table already for testing.

Line 155 in my code is still there. What I removed was an if (isset($_SESSION statement because I was trying to identify the index error I received, but it didn’t work.

This is line 155:

<span class="mr-2 d-none d-lg-inline text-gray-600 small">Welcome, <?php echo $_SESSION["first_name"]; ?>!</span> 

Ah, that’s much easier to see, thanks.

Now, where is the code that puts something in to that session variable?

If there’s a chance the user will display that page when they are not logged in, i.e. when the session variable will not be set, then you’ll have to handle that. And if they should not be able to, then your check to see if it’s set would then be able to redirect them from a page they should not be seeing. Obviously that only applies if the user could never have a blank first-name.

Forgive me for misunderstanding, but here is my overall goal:

I have a MySQL database that will hold the list of users who will control the members database. I’m wanting to have the index page (where the members database is located) only appear if someone is logged in. If they try to go to the index page without logging in, they should be redirected to the login page. When they logout, the session needs to be destroyed so that another user can login and a new session is created.

I have a logout script already:

<?php

// Initialize the session
session_start();
 
// Unset all of the session variables
$_SESSION = array();
 
// Destroy the session.
session_destroy();
 
// Redirect to login page
header("location: login.php");
exit;

?>

And I have the code in my OP, but I keep seeing an undefined index error at the top of my homepage. I know I have to identify it somehow, but I’m not sure where to do it. I tried using an if(isset($_SESSION statement to solve this, but it isn’t working.

Well, that’s the code you need, I think. Perhaps you could post what you had so someone might be able to spot why it isn’t working.

I tried this:

if (isset($_SESSION['first_name'])){
    echo 'Hello' . "first_name";
}
else 'Login';

But it isn’t working… maybe I’m approaching it wrong?

You’ve been here long enough to know that isn’t a useful error report. In what way is it not working?

This line won’t work:

else 'Login';

of course.

Obviously if you’re going to do a header redirect you’ll have to have that before any browser output, so do the check at the start. You probably knew that.

It doesn’t work because the index error is still there. It’s supposed to say “Welcome, {first_name here}!” Instead it says:

Welcome, Notice: Undefined index: first_name in C:\xampp\htdocs\ccrp\index.php on line 155!

Other than that, I don’t see any code specific errors. Not even in my browser.

I can’t help based on the error message, I need to see the code. Like I said, though, if you’re intending to redirect them somewhere, there’s no point checking this on line 155, you need to check at the start.

You do have a session_start() at the very beginning of the PHP code, before any browser output, don’t you?

Yes, on line 5:

<?php

require_once "api/dbconnect.php";

session_start();

?>

This is the only PHP code I have.

No it’s not. That wouldn’t be producing your “undefined index” error message. Show us that bit.

I already have. That error is coming from this line:

<span class="mr-2 d-none d-lg-inline text-gray-600 small">Welcome, <?php echo $_SESSION["first_name"]; ?>!</span>

But that line doesn’t have your isset code around it, so you’re accessing an array element that doesn’t exist. You need to reinstate the isset check.

If you intend to redirect, you could stick the isset check just after your session_start, as that would be before browser output.

I intend to redirect after the user logs in.

Here is another isset I tried:

if (isset($_SESSION['first_name'])) {
	$first_name = $_GET['first_name'];
}

Maybe I don’t understand how isset works…

You do, but you check to see if it exists in $_SESSION, then if it does, try to retrieve it from $_GET.

Sorry, I thought this was the page that is only accessible to people who have already logged in, and that you wanted to redirect them if the session var was not set.

That is correct. My apologies on typing that out wrong…

I would just do this:

<?php

require_once "api/dbconnect.php";

session_start();

if (!isset($_SESSION['first_name'])) { 
   header("location: wherever");
   exit();
}

?>

You might use something else to determine whether they’re logged in or not. But by the time you get to line 155, you can already know whether the session var is set, and don’t need to check again.

Well, it redirects, but now my login page won’t redirect to the index page when the session starts.

<?php

// Initialize the session
session_start();
 
// Check if the user is already logged in, if yes then redirect him to database
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
    header("location: index.php");
    exit;
}
 
// Include config file
require_once "api/dbconnect.php";
 
// Define variables and initialize with empty values
$username = $password = "";
$username_err = $password_err = "";
 
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    // Check if username is empty
    if(empty(trim($_POST["username"]))){
        $username_err = "Please enter username.";
    } else{
        $username = trim($_POST["username"]);
    }
    
    // Check if password is empty
    if(empty(trim($_POST["password"]))){
        $password_err = "Please enter your password.";
    } else{
        $password = trim($_POST["password"]);
    }
    
    // Validate credentials
    if(empty($username_err) && empty($password_err)){
        // Prepare a select statement
        $sql = "SELECT id, username, password FROM admins WHERE username = :username";
        
        if($stmt = $pdo->prepare($sql)){
            // Bind variables to the prepared statement as parameters
            $stmt->bindParam(":username", $param_username, PDO::PARAM_STR);
            
            // Set parameters
            $param_username = trim($_POST["username"]);
            
            // Attempt to execute the prepared statement
            if($stmt->execute()){
                // Check if username exists, if yes then verify password
                if($stmt->rowCount() == 1){
                    if($row = $stmt->fetch()){
                        $id = $row["id"];
                        $username = $row["username"];
                        $hashed_password = $row["password"];
                        if(password_verify($password, $hashed_password)){
                            // Password is correct, so start a new session
                            session_start();
                            
                            // Store data in session variables
                            $_SESSION["loggedin"] = true;
                            $_SESSION["id"] = $id;
                            $_SESSION["username"] = $username;                            
                            
                            // Redirect user to welcome page
                            header("location: index.php");
                        } else{
                            // Display an error message if password is not valid
                            $password_err = "The password you entered was not valid.";
                        }
                    }
                } else{
                    // Display an error message if username doesn't exist
                    $username_err = "No account found with that username.";
                }
            } else{
                echo "Something went wrong. Please try again later.";
            }
        }
        
        // Close statement
        unset($stmt);
    }
    
    // Close connection
    unset($pdo);
}
?>

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>CCRP - Database Login</title>

  <!-- Custom fonts for this template-->
  <link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template-->
  <link href="css/sb-admin-2.min.css" rel="stylesheet">

</head>

<body class="bg-gradient-primary">

  <div class="container">

    <!-- Outer Row -->
    <div class="row justify-content-center">

      <div class="col-xl-10 col-lg-12 col-md-9">

        <div class="card o-hidden border-0 shadow-lg my-5">
          <div class="card-body p-0">
            <!-- Nested Row within Card Body -->
            <div class="row">
              <div class="col-lg-6 d-none d-lg-block"><img src="img/rpwall.jpg" width="485" height="600"></div>
              <div class="col-lg-6">
                <div class="p-5">
                  <div class="text-center">
                    <h1 class="h4 text-gray-900 mb-4">Welcome</h1>
                  </div>
                  <form class="user">
                    <div class="form-group">
                      <input type="email" class="form-control form-control-user" id="exampleInputEmail" aria-describedby="emailHelp" placeholder="Username">
                    </div>
                    <div class="form-group">
                      <input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password">
                    </div>
                    <div class="form-group">
                      <div class="custom-control custom-checkbox small">
                        <input type="checkbox" class="custom-control-input" id="customCheck">
                        <!-- <label class="custom-control-label" for="customCheck">Remember Me</label> -->
                      </div>
                    </div>
                    <a href="index.php" class="btn btn-primary btn-user btn-block" style="background-color:#a40000; border-color:#a40000;">
                      Login
                    </a>
                    <hr>
                    <!-- <a href="index.html" class="btn btn-google btn-user btn-block">
                      <i class="fab fa-google fa-fw"></i> Login with Google
                    </a>
                    <a href="index.html" class="btn btn-facebook btn-user btn-block">
                      <i class="fab fa-facebook-f fa-fw"></i> Login with Facebook
                    </a> -->
                  </form>
                  <div class="text-center">
                    <a class="small" href="forgot-password.php">Reset Password</a>
                  </div>
                  <div class="text-center">
                    <a class="small" href="register.php">Create a Database Account</a>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

      </div>

    </div>

  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="vendor/jquery/jquery.min.js"></script>
  <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="js/sb-admin-2.min.js"></script>

</body>

</html>