Skip to content

Student Listing: Adding User Logins - Signup

Creating a Signup Page with the Usual Bootstrap Template with a Card

Let's create a signup.php script using a Bootstrap template and add a Card for our content with a header for the title of the page:

signup.php - Student Listing: using Bootstrap Template with Card

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<?php
    require_once('pagetitles.php');
    $page_title = SL_SIGNUP_PAGE;
?>
<html>
  <head>
    <link rel="stylesheet"
          href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
          integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
          crossorigin="anonymous">
    <title><?= $page_title ?></title>
  </head>
  <body>
    <div class="card">
      <div class="card-body">
        <h1><?= $page_title ?></h1>
        <hr/>
      </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
            integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
            crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js"
            integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
            crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"
            integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
            crossorigin="anonymous"></script>
  </body>
</html>

NOTE: Notice the setting and usage of our page title ($page_title = SL_SIGNUP_PAGE;) from our pagetitles.php constants script.

Add Self Referencing Form for Signing up new Students

Since this will be a self referencing page, we only want to display the form in certain circumstances. After the <hr/> add a boolean flag for whether we show the form or not, and set it to true. Then create one condition for processing the submitted form, and another for displaying the form:

signup.php - Student Listing: Boolean to Display or Process Form

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
<body>
<div class="card">
  <div class="card-body">
    <h1><?= $page_title ?></h1>
    <hr/>
  </div>
  <hr/>
  <?php
      $show_sign_up_form = true;

      if (isset($_POST['signup_submission']))
      {

      }

      if ($show_sign_up_form):
      ?>

      <?php
      endif;
  ?>
</div>
...
</body>
...

Now let's create our form within the if ($show_sign_up_form) condition:

signup.php - Student Listing: Form

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
...
<body>
<div class="card">
  <div class="card-body">
    <h1><?= $page_title ?></h1>
    <hr/>
  </div>
  <hr/>
  <?php
      $show_sign_up_form = true;

      if (isset($_POST['signup_submission']))
      {

      }

      if ($show_sign_up_form):
  ?>
        <form class="needs-validation" novalidate method="POST"
              action="<?= $_SERVER['PHP_SELF'] ?>">
          <div class="form-group row">
            <label for="first_name"
                class="col-sm-2 col-form-label-lg">First Name</label>
            <div class="col-sm-4">
              <input type="text" class="form-control"
                  id="first_name" name="first_name"
                  placeholder="Enter a first name"
                  required>
              <div class="invalid-feedback">
                  Please provide a valid first name.
              </div>
            </div>
          </div>
          <div class="form-group row">
            <label for="last_name"
                class="col-sm-2 col-form-label-lg">Last Name</label>
            <div class="col-sm-4">
              <input type="text" class="form-control"
                  id="last_name" name="last_name"
                  placeholder="Enter a last name"
                  required>
              <div class="invalid-feedback">
                  Please provide a valid last name.
              </div>
            </div>
          </div>
          <div class="form-group row">
            <label for="email"
                class="col-sm-2 col-form-label-lg">Email Address</label>
            <div class="col-sm-4">
              <input type="email" class="form-control"
                  id="email" name="email"
                  placeholder="Enter an email address"
                  required>
              <div class="invalid-feedback">
                  Please provide a valid email address.
              </div>
            </div>
          </div>
          <div class="form-group row">
            <label for="user_name"
                class="col-sm-2 col-form-label-lg">User Name</label>
            <div class="col-sm-4">
              <input type="text" class="form-control"
                  id="user_name" name="user_name"
                  placeholder="Enter a user name"
                  required>
              <div class="invalid-feedback">
                  Please provide a valid user name.
              </div>
            </div>
          </div>
          <div class="form-group row">
            <label for="password"
                class="col-sm-2 col-form-label-lg">Password</label>
            <div class="col-sm-4">
              <input type="password" class="form-control"
                  id="password" name="password"
                  placeholder="Enter a password" required>
              <div class="form-group form-check">
                <input type="checkbox"
                    class="form-check-input"
                    id="show_password_check"
                    onclick="togglePassword()">
                <label class="form-check-label"
                    for="show_password_check">Show Password</label>
              </div>
              <div class="invalid-feedback">
                  Please provide a valid password.
              </div>
            </div>
          </div>
          <button class="btn btn-primary" type="submit"
              name="signup_submission">Sign Up
          </button>
        </form>
  <?php
      endif;
  ?>
</div>
...
</body>
...

In addition to using Bootstrap's client side validation, notice that we have a checkbox that allows the user to show their password or not:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<div class="form-group row">
  <label for="password"
      class="col-sm-2 col-form-label-lg">Password</label>
  <div class="col-sm-4">
    <input type="password" class="form-control"
        id="password" name="password"
        placeholder="Enter a password" required>
    <div class="form-group form-check">
      <input type="checkbox"
          class="form-check-input"
          id="show_password_check"
          onclick="togglePassword()">
      <label class="form-check-label"
          for="show_password_check">Show Password</label>
    </div>
    <div class="invalid-feedback">
        Please provide a valid password.
    </div>
  </div>
</div>

In addition to the JavaScript necessarry for Bootstrap's client side validation, you also need to enable the onclick attribute set to a function you create called togglePassword() for toggling the display of the password. Add the following JavaScript in <script> tags following the form:

signup.php - Student Listing: Javascript for validating form and toggling password

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
        </form>
  <?php
      endif; // Display signup student form
  ?>
</div>
  <script>
  // JavaScript for disabling form submissions if there are invalid fields
  (function() {
    'use strict';
    window.addEventListener('load', function() {
      // Fetch all the forms we want to apply custom Bootstrap validation styles to
      var forms = document.getElementsByClassName('needs-validation');
      // Loop over them and prevent submission
      var validation = Array.prototype.filter.call(forms, function(form) {
        form.addEventListener('submit', function(event) {
          if (form.checkValidity() === false) {
            event.preventDefault();
            event.stopPropagation();
          }
          form.classList.add('was-validated');
        }, false);
      });
    }, false);
  })();

  // JavaScript for showing and hiding the password
  function togglePassword() {
      var password_entry = document.getElementById("password");
      if (password_entry.type === "password") {
        password_entry.type = "text";
      } else {
        password_entry.type = "password";
      }
  }
  </script>
...
</body>

Inserting the new User and Student Data Into the Database

When a user enters the required fields into the form and submits it, we will insert the data into the database. We'll do this inside a code block that checks if the user submitted the form. Add the following condition just below the $show_sign_up_form = true; line:

signup.php - Student Listing: Condition for Adding Student Data to Database

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
...
$show_sign_up_form = true;

if (isset($_POST['signup_submission']))
{
    // Code to insert new user and student data into database
    ...
}

if ($display_add_student_form)
{
...

Here are the things we need to do in this condition:

  • Grab all the fields from the form
  • Check to see if the user already exists
    • If the user exists, display an error to the page
  • If the user does not exist, do the following:
    • Insert a new entry in the studentListing table for this user
    • Grab the last inserted ID for this new studentListing row
    • Create a salted hashed password
    • Insert a new entry in the user table for this user tying the studentListing ID to this user
    • Display a message to the page that the user was successfully added and display a link to login

signup.php - Student Listing: Adding Student Data to Database

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
$show_sign_up_form = true;

if (isset($_POST['signup_submission']))
{
    // Get first & last name, email, and user name & password
    $first_name = $_POST['first_name'];
    $last_name = $_POST['last_name'];
    $email = $_POST['email'];
    $user_name = $_POST['user_name'];
    $password = $_POST['password'];

    if (!empty($user_name) && !empty($password))
    {
        require_once('dbconnection.php');

        require_once('queryutils.php');

        $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
                or trigger_error(
                        'Error connecting to MySQL server for DB_NAME.', 
                        E_USER_ERROR
                );

        // Check if user already exists
        $query = "SELECT * FROM user WHERE user_name = ?";

        $results = parameterizedQuery($dbc, $query, 's', $user_name)
                or trigger_error(mysqli_error($dbc), E_USER_ERROR);

        // IF user does not exist, create an account for them
        if (mysqli_num_rows($results) == 0)
        {
            // Create student entry for new user
            $query = "INSERT INTO studentListing (`first_name`, `last_name`, `email`, `image_file`) "
                    . "VALUES (?, ?, ?, '')";

            $results = parameterizedQuery($dbc, $query, 'sss', $first_name, $last_name, $email)
                    or trigger_error(mysqli_error($dbc), E_USER_ERROR);

            $id_of_new_student_listing = mysqli_insert_id($dbc);

            $salted_hashed_password = password_hash($password, PASSWORD_DEFAULT);

            $query = "INSERT INTO user (`user_name`, `password_hash`, `studentListing_id`) "
                    . "VALUES (?, '$salted_hashed_password', $id_of_new_student_listing)";

            $results = parameterizedQuery($dbc, $query, 's', $user_name)
                    or trigger_error(mysqli_error($dbc), E_USER_ERROR);

            // Direct the user to the login page
            echo "<h4><p class='text-success'>Thank you for signing up <strong>$user_name</strong>! "
                    . "Your new account has been successfully created.<br/>"
                    . "You're now ready to <a href='login.php'>log in</a>.</p></h4>";

            $show_sign_up_form = false;
        }
        else // An account already exists for this user
        {
            echo "<h4><p class='text-danger'>An account already exists for this username: "
                    .  "<span class='font-weight-bold'> ($user_name)</span>. Please use  "
                    .  "a different user name.</p></h4><hr/>";

        }
    }
    else
    {
        // Output error message
        echo "<h4><p class='text-danger'>You must enter both a user name 
            and password.</p></h4><hr/>";
    }
}

if ($show_sign_up_form):
...

Complete Code Listing

signup.php - Student Listing: Complete Code Listing

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<!DOCTYPE html>
<?php
    require_once('pagetitles.php');
    $page_title = SL_SIGNUP_PAGE;
?>
<html>
  <head>
    <title><?= $page_title ?></title>
    <link rel="stylesheet"
        href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
        integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
        crossorigin="anonymous">
  </head>
  <body>
    <div class="card">
      <div class="card-body">
        <h1><?= $page_title ?></h1>
        <hr/>
        <?php
            $show_sign_up_form = true;

            if (isset($_POST['signup_submission']))
            {
                // Get first & last name, email, and user name & password
                $first_name = $_POST['first_name'];
                $last_name = $_POST['last_name'];
                $email = $_POST['email'];
                $user_name = $_POST['user_name'];
                $password = $_POST['password'];

                if (!empty($user_name) && !empty($password))
                {
                    require_once('dbconnection.php');

                    require_once('queryutils.php');

                    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
                            or trigger_error(
                                    'Error connecting to MySQL server for DB_NAME.', 
                                    E_USER_ERROR);

                    // Check if user already exists
                    $query = "SELECT * FROM user WHERE user_name = ?";

                    $results = parameterizedQuery($dbc, $query, 's', $user_name)
                            or trigger_error(mysqli_error($dbc), E_USER_ERROR);

                    // IF user does not exist, create an account for them
                    if (mysqli_num_rows($results) == 0)
                    {
                        // Create student entry for new user
                        $query = "INSERT INTO studentListing (`first_name`, `last_name`, `email`, `image_file`) "
                                . "VALUES (?, ?, ?, '')";

                        $results = parameterizedQuery($dbc, $query, 'sss', $first_name, $last_name, $email)
                                or trigger_error(mysqli_error($dbc), E_USER_ERROR);

                        $id_of_new_student_listing = mysqli_insert_id($dbc);

                        $salted_hashed_password = password_hash($password, PASSWORD_DEFAULT);

                        $query = "INSERT INTO user (`user_name`, `password_hash`, `studentListing_id`) "
                                . "VALUES (?, '$salted_hashed_password', $id_of_new_student_listing)";

                        $results = parameterizedQuery($dbc, $query, 's', $user_name)
                                or trigger_error(mysqli_error($dbc), E_USER_ERROR);

                        // Direct the user to the login page
                        echo "<h4><p class='text-success'>Thank you for signing up <strong>$user_name</strong>! "
                                . "Your new account has been successfully created.<br/>"
                                . "You're now ready to <a href='login.php'>log in</a>.</p></h4>";

                        $show_sign_up_form = false;
                    }
                    else // An account already exists for this user
                    {
                        echo "<h4><p class='text-danger'>An account already exists for this username: "
                                .  "<span class='font-weight-bold'> ($user_name)</span>. Please use  "
                                .  "a different user name.</p></h4><hr/>";

                    }
                }
                else
                {
                    // Output error message
                    echo "<h4><p class='text-danger'>You must enter both a user name 
                        and password.</p></h4><hr/>";
                }
            }

            if ($show_sign_up_form):
        ?>
            <form class="needs-validation" novalidate method="POST"
                  action="<?= $_SERVER['PHP_SELF'] ?>">
              <div class="form-group row">
                <label for="first_name"
                    class="col-sm-2 col-form-label-lg">First Name</label>
                <div class="col-sm-4">
                  <input type="text" class="form-control"
                      id="first_name" name="first_name"
                      placeholder="Enter a first name"
                      required>
                  <div class="invalid-feedback">
                      Please provide a valid first name.
                  </div>
                </div>
              </div>
              <div class="form-group row">
                <label for="last_name"
                    class="col-sm-2 col-form-label-lg">Last Name</label>
                <div class="col-sm-4">
                  <input type="text" class="form-control"
                      id="last_name" name="last_name"
                      placeholder="Enter a last name"
                      required>
                  <div class="invalid-feedback">
                      Please provide a valid last name.
                  </div>
                </div>
              </div>
              <div class="form-group row">
                <label for="email"
                    class="col-sm-2 col-form-label-lg">Email Address</label>
                <div class="col-sm-4">
                  <input type="email" class="form-control"
                      id="email" name="email"
                      placeholder="Enter an email address"
                      required>
                  <div class="invalid-feedback">
                      Please provide a valid email address.
                  </div>
                </div>
              </div>
              <div class="form-group row">
                <label for="user_name"
                    class="col-sm-2 col-form-label-lg">User Name</label>
                <div class="col-sm-4">
                  <input type="text" class="form-control"
                      id="user_name" name="user_name"
                      placeholder="Enter a user name"
                      required>
                  <div class="invalid-feedback">
                      Please provide a valid user name.
                  </div>
                </div>
              </div>
              <div class="form-group row">
                <label for="password"
                    class="col-sm-2 col-form-label-lg">Password</label>
                <div class="col-sm-4">
                  <input type="password" class="form-control"
                      id="password" name="password"
                      placeholder="Enter a password" required>
                  <div class="form-group form-check">
                    <input type="checkbox"
                        class="form-check-input"
                        id="show_password_check"
                        onclick="togglePassword()">
                    <label class="form-check-label"
                        for="show_password_check">Show Password</label>
                  </div>
                  <div class="invalid-feedback">
                      Please provide a valid password.
                  </div>
                </div>
              </div>
              <button class="btn btn-primary" type="submit"
                  name="signup_submission">Sign Up
              </button>
            </form>
        <?php
            endif;
        ?>
      </div>
    </div>
    <script>
      // JavaScript for disabling form submissions if there are invalid fields
      (function () {
          'use strict';
          window.addEventListener('load', function () {
            // Fetch all the forms we want to apply custom Bootstrap validation styles to
            var forms = document.getElementsByClassName('needs-validation');
            // Loop over them and prevent submission
            var validation = Array.prototype.filter.call(forms, function (form) {
                form.addEventListener('submit', function (event) {
                  if (form.checkValidity() === false) {
                      event.preventDefault();
                      event.stopPropagation();
                  }
                  form.classList.add('was-validated');
                }, false);
            });
          }, false);
      })();

      function togglePassword() {
          var password_entry = document.getElementById("password");
          if (password_entry.type === "password") {
            password_entry.type = "text";
          } else {
            password_entry.type = "password";
          }
      }
    </script>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
        crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
        integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI"
        crossorigin="anonymous"></script>
  </body>
</html>