I have made a login system, however, I don't know how to style some of it

Viewed 65

So, I have been working on a login page, and it has been working beautifully so far. However, I cannot style where the error message appears. Here is the code:

-- The login.php file --


<?php
include_once '../resources/session.php';
include_once '../resources/database.php';
include_once '../resources/utilities.php';

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

    // array to hold errors
    $form_errors = array();

    // validate
    $required_fields = array('username', 'password');

    $form_errors = array_merge($form_errors, check_empty_fields($required_fields));

    if(empty($form_errors)){

        // collect form data
        $user = $_POST['username'];
        $password = $_POST['password'];

        //  check if user exists in the database
        $sqlQuery = "SELECT * FROM users WHERE username = :username";
        $statement = $db->prepare($sqlQuery);
        $statement->execute(array(':username' => $user));

        while($row = $statement->fetch()){
            $id = $row['id'];
            $hashedpassword = $row['password'];
            $username = $row['username'];

            if(password_verify($password, $hashedpassword)){
                $_SESSION['id'] = $id;
                $_SESSION['username'] = $username;
                redirectTo('dashboard');
            }
            else{
                $result = flashMessage("Invalid username or password");
            }
        }

    }
    else{
        if(count($form_errors) == 1){
            $result = flashMessage("There was 1 error in the form");
        }
        else{
            $result = flashMessage("There were " .count($form_errors). " errors in the form");
        }
    }
}
?>

<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Login</title>
        <link rel="stylesheet" href="../css/loginstyles.css">
        <link rel="stylesheet"
        href="https://fonts.googleapis.com/css?family=Open+Sans">
        <script src="https://kit.fontawesome.com/586353a8fa.js" crossorigin="anonymous"></script>
        <style>
            body{
                font-family: 'Open Sans', serif;
            }
            .links{
                text-decoration: none;
                color: black;
                font-size: 70%;
            }
            .links:hover{
                color: #21ada8;
            }

        </style>
    </head>
    <body>
        <a href="../html/index.html"><i class="far fa-arrow-alt-circle-left" style="color: #21ada1;"></i></a><br>
        <img src="../img/loginimg.svg" alt="login" style="width: 55%; margin-top: 17%;">
        <div class="login-wrapper">
            <h2 class="formtitle">Login Form</h2>
            <?php if(isset($result)) echo $result; ?>
            <?php if(!empty($form_errors)) echo show_errors($form_errors); ?>
            <form class="loginform" action="" method="post">
                    <table>
                        <tr>
                            <td><input type="text" value="" name="username" autocomplete="off" placeholder="username" class="usernameinput" style="height: 80px; border: none;"></td>
                        </tr>
                        <tr>
                            <td><input type="password" value="" name="password" autocomplete="off" placeholder= "password" class="passwordinput"style="width: 300px; height: 80px; margin-top: 2%; border: none;"></td>
                        </tr>
                        <tr>
                            <td><a class="links" href="forgot_password.php">Forgot your Password?</a></td>
                        </tr>
                        <tr>
                            <td><input style="float: right;" type="submit" name="loginBtn" class="loginBtn" value="Login"></td>
                        </tr>
                        <tr>
                            <td><a class="links" href="signup.php">Not a Member Yet? Sign Up!</a></td>
                        </tr>
                    </table>
            </form>
        </div>
    </body>
</html>

-- The loginstyles.css file --

.loginform{
    margin-left: 70%;
  margin-top: -30%;
}

.loginform input{
    width: 100%;
}

.usernameinput:focus{
    outline: none;
    background:
      linear-gradient(#21ada8, #00ced1) center bottom 5px /calc(100% - 10px)2px no-repeat;
}

.passwordinput:focus{
    outline: none;
    background:
      linear-gradient(#21ada8, #00ced1) center bottom 5px /calc(100% - 10px)2px no-repeat;
}

.loginBtn{
    border: none;
    text-decoration: none;
    padding-left: 10%;
    padding-right: 10%;
    padding-top: 3%;
    padding-bottom: 3%;
    background-color: #00ced1;
    margin-top: 5%;
    margin-bottom: 5%;
}

.loginBtn:focus{
  outline: none;
}

.loginBtn:hover{
    background-color: #00a3a6;
}

.usernameinput::placeholder{
    color: #c0c0c0;
}

.passwordinput::placeholder{
    color: #c0c0c0;
}

.usernameinput{
    background:
      linear-gradient(#c0c0c0, #c0c0c0) center bottom 5px /calc(100% - 10px)2px no-repeat;
    font-size: 18px;
}

.passwordinput{
    background:
      linear-gradient(#c0c0c0, #c0c0c0) center bottom 5px /calc(100% - 10px)2px no-repeat;
  font-size: 18px;
}

.formtitle{
    font-size: 30px;
    margin-left: 73%;
    position: fixed;
  margin-top: -10%;
}

.backBtn {
  color: red !important;
}

.login-wrapper{
    // border: 1px solid gray;

}

-- The utilities.php file --


<?php

/**
    * @param $required_fields_array, n array containing the list of all required fields
    * @return array, containing all errors
*/

// start

function check_empty_fields($required_fields_array){
        // initialize an array to store error messages
        $form_errors = array();

        // loop throgh the required fields array and popular the form error array
        foreach ($required_fields_array as $name_of_field){
            if(!isset($_POST[$name_of_field]) || $_POST[$name_of_field] == NULL){
                $form_errors[] = $name_of_field . " is a required field";

            }

        }

        return $form_errors;
}

/**
    * @param $fields_to_check_length, an array containing the name of fields
    * for which we wnt th check min required length e.g. array('username' => 4, 'email' => 12)
    * @return array, containing all errors
*/

function check_min_length($fields_to_check_length){
    //initialize an array to store error messages
    $form_errors = array();

    foreach($fields_to_check_length as $name_of_field => $minimum_length_required){
        if(strlen(trim($_POST[$name_of_field])) < $minimum_length_required){
            $form_errors[] = $name_of_field . " is too short, must be {$minimum_length_required} characters long";

        }
    }
    return $form_errors;
}

/**
    * @param $data, store a key/value pair array where key is the name of the form control
    * in this case 'email' and value is the input entered by the user
    * @return array, containing email error
*/

function check_email($data){
    //initialize an array to store error messages
    $form_errors = array();
    $key = 'email';
    // check if the key email exists in data array
    if(array_key_exists($key, $data)){

        // check if the email field has a value
        if($_POST[$key] != null){

            // remove all illegal characters from email
            $key = filter_var($key, FILTER_SANITIZE_EMAIL);

            // check if input is a valid email addresss
            if(filter_var($_POST[$key], FILTER_VALIDATE_EMAIL) === false){
                $form_errors[] = $key . " is not a valid email address";
            }
        }
    }

    return $form_errors;
}

/**
    * @param $form_errors_array, the array holding all
    * errors which we want to loop through
    * @return string, list containing all error messages
*/

function show_errors($form_errors_array){
    $errors = "<p><ul style ='color: red;'>";

    // loop through error array and display all items in a list
    foreach($form_errors_array as $the_error){
        $errors .= "<li> {$the_error} </li>";
    }
    $errors .= "</ul><p>";
    return $errors;
}

function flashMessage($message, $passOrFail = "Fail"){
  if($passOrFail === "Pass"){
    $data = "<p style='padding: 20px; color: green; margin-left: 73%;'>{$message}</p>";
  }
  else{
    $data = "<p style='padding: 20px; color: red; margin-left: 73%;'>{$message}</p>";
  }

  return $data;
}

function redirectTo($page){
  header("Location: {$page}.php");
}

function checkDuplicateEntries($table, $column_name, $value, $db){

  try{
    $sqlQuery = "SELECT * FROM " .$table. " WHERE " .$column_name. "=:$column_name";
    $statement = $db->prepare($sqlQuery);
        $statement->execute(array(':$column_name' => $value));

    if ($row = $statement->fetch()){
      return true;
    }
    return false;
  }
  catch (PDOException $ex){
    // handle exception
  }

}

What happens is, the error message appears at the bottom of the screen instead of under Login Form. And also, the form title gets dragged down too, so it looks like this:

enter image description here

Any help is greatly appreciated!

Thanks in advance!

2 Answers

This is how I do it

<?php

function login_user()
{
    if (is_post_request() && is_request_same_domain() && isset($_POST['login-submit'])) {
        $username = $_POST['username'] ?? '';
        $password = $_POST['password'] ?? '';
        $csrf_token = $_POST['csrf_token'] ?? '';

        $errors = [];

        if (!csrf_token_is_valid($csrf_token) || !csrf_token_is_recent()) {
            $errors['form'] = 'The security token is missing.';
        }

        if (empty($username)) {
            $errors['username'] = 'Wrong username or email';
        }

        if (empty($password)) {
            $errors['password'] = 'Wrong password';
        }

        // if there were no errors, try to login
        if (empty($errors)) {
            $username = strtolower(str_replace(' ', '', $username));
            // returns an array with user info
            $user = find_by_username($username);
            // test if user found and password is correct
            if ($user && password_verify($password, $user['password'])) {
                // Mark user as logged in
                login($user);

                redirect_to(SITE_URL . '/admin/index');
            } else {
                // username not found or password does not match
                $errors['form'] = 'Invalid email or password';
                return $errors;
            }
        } else {
            return $errors;
        }
    }
}

Then in HTML

<?php
$errors = login_user();
echo isset($errors['form']) ? '<div class="alert alert-danger rounded">' . h($errors['form']) . '</div>' : '';
?>
<form action="" method="post">
    <div class="form-group">
        <label id="username" class="form-label">Username or Email</label>
        <input type="text" name="username" value="<?php if (isset($_POST['username'])) echo $_POST['username']; ?>" id="username" class="form-control">
        <div class="text-danger mt-1"><?php echo $errors['username'] ?? ''; ?></div>
    </div>
    <div class="form-group">
        <label id="password" class="form-label">Password</label>
        <input type="password" name="password" id="password" class="form-control">
        <div class="text-danger mt-1"><?php echo $errors['password'] ?? ''; ?></div>
    </div>
    <?php echo csrf_token_tag(); ?>
    <div class="text-center">
        <button type="submit" name="login-submit" class="btn btn-primary">Log In</button>
        <a class="fp-link" href="forgot">Forgot Password?</a>
    </div>
</form>

You should move the show_errors to the form bottom and format with html.

 <div class="login-wrapper">
            <h2 class="formtitle">Login Form</h2>
            <?php if(isset($result)) echo $result; ?>
            <?php if(!empty($form_errors)) echo show_errors($form_errors); ?>
            <form class="loginform" action="" method="post">

To something like:

 <div class="login-wrapper">
            <h2 class="formtitle">Login Form</h2>
            <form class="loginform" action="" method="post">
<table>
                        <tr>
                            <td><input type="text" value="" name="username" autocomplete="off" placeholder="username" class="usernameinput" style="height: 80px; border: none;"></td>
                        </tr>
                        <tr>
                            <td><input type="password" value="" name="password" autocomplete="off" placeholder= "password" class="passwordinput"style="width: 300px; height: 80px; margin-top: 2%; border: none;"></td>
                        </tr>
                        <tr>
                            <td><a class="links" href="forgot_password.php">Forgot your Password?</a></td>
                        </tr>
<?php if(isset($result)){ ?>
                        <tr>
                            <td><span><?=$result?></span></td>
                        </tr>
<?php } ?>
<?php if(!empty($form_errors)){ ?>
                        <tr>
                            <td><span><?=show_errors($form_errors)?></span></td>
                        </tr>
<?php } ?>

                        <tr>
                            <td><input style="float: right;" type="submit" name="loginBtn" class="loginBtn" value="Login"></td>
                        </tr>
                        <tr>
                            <td><a class="links" href="signup.php">Not a Member Yet? Sign Up!</a></td>
                        </tr>
                    </table>

Then you get the errors inside the table structure.

I advise you that could use some modern structures to style the html like css flex.

Related