0

I am working on a small PHP and MySQL project for a course that I am taking this semester. It's a very basic mock fan page site that will have features such as user management, file upload, email sending, and more. The issue I am having arose when I began trying to refresh or redirect on the login screen post submit. The basic structure of the site uses templating with: - header.php - index.php (or whatever other page for content) - footer.php

Header and footer.php are included on all user visible pages.

In my header.php I have the following code:

<?php
session_start();
// Check and set the logged_in var
if (isset($_SESSION['username'])){
  $logged_in = true;
}else {
  $logged_in = false;
}?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="HandheldFriendly" content="True">
  <title>Life's A Garden, Dig It!</title>
  <link rel="stylesheet" type="text/css" media="screen" href="css/concise.min.css" />
  <link rel="stylesheet" type="text/css" media="screen" href="css/masthead.css" />
  <link rel="stylesheet" type="text/css" media="screen" href="css/style.css" />
</head>
<body>

  <header container class="siteHeader">
    <div row>
      <h1 column=4 class="logo"><a href="index.php">Welcome</a></h1>
      <nav column="8" class="nav">
        <ul>
          <li><a href="books.php">Books</a></li>
<?php 
        // If user is not logged in nav bar = Books, Quotes, Login, Register
        // If user is logged in nav bar = Books, Stories, Quotes, Contact, Uploads, Logout
          if($logged_in){
            echo '<li><a href="#">Stories</a></li>';
          }
          ?>

          <li><a href="#">Quotes</a></li>

          <?php 
        // Only displayed if user is logged in
          if($logged_in){
            echo '<li><a href="email.php">Contact</a></li>';
            echo '<li><a href="#">Uploads</a></li>';
            echo '<li><a href="logout.php">Logout</a></li>';
          }else{
            echo '<li><a href="login.php">Login</a></li>';
            echo '<li><a href="register.php">Register</a></li>';
          }
?>

        </ul>
      </nav>
    </div>
  </header>
  <main container class="siteContent">

This is my footer.php:

        <!-- Script 8.3 - footer.html -->
  <!-- END CHANGEABLE CONTENT. -->
  </main>

  <footer container class="siteFooter">
    <p>Design uses <a href="http://concisecss.com/">Concise CSS Framework</a></p>
  </footer>

</body>
</html>

This is my login.php (which is where I'm having errors):

<?php
// For debugging
ini_set('display_errors', 1);
error_reporting(E_ALL);

// Page title
define('TITLE', 'Login');

// Include header
include('templates/header.php');

// Establish DB connection
require('../mysqli_connect.php');

// Page introduction
print '<h2>Login Form</h2>
    <p>Users who are logged in can take advantage of certain features like this, that, and the other thing.</p>';

// Check if the form has been submitted:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {

    // Sanitize and store input vars for login
    $username_input = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['username'])));
    $password_input = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['password'])));


    // Retrieve query results for username entered
    $query = "SELECT * FROM users WHERE username='$username_input'";



    if ($result = mysqli_query($dbc, $query)) {

        $row = mysqli_fetch_array($result);



        // Check if that username was found in query. If not found error, if found  store the associated pwd hash.
        if (count($row) == NULL){
            print '<p class="text--error">Error: The username you entered was not found in the system!<br>Go back and try again.</p>';

        } else{
            // Query resulted in good results for 1 matching username in DB, now save pwd hash in the db.
            $db_pwd_hash = $row['password'];

            // Update username session var
            $_SESSION['username'] = $username_input;

            // Redirect to homepage, refreshes nav bar view
            header('Location: index.php');
        }



    }

    // Handle the form:
    if ( (!empty($username_input)) && (!empty($password_input)) ) {

        if ( password_verify($password_input, $db_pwd_hash) ) { // Correct!

            print '<p class="text--success">You are logged in!<br>Now you can blah, blah, blah...</p>';


        } else { // Incorrect!

            print '<p class="text--error">The submitted email address and password do not match those on file!<br>Go back and try again.</p>';

        }

    } else { // Forgot a field.

        print '<p class="text--error">Please make sure you enter both an email address and a password!<br>Go back and try again.</p>';

    }

} else { // Display the form.

    print '<form action="login.php" method="post">
    <p><label for="username">Username:</label><input type="text" name="username"></p>
    <p><label for="password">Password:</label><input type="password" name="password"></p>
    <p><input type="submit" name="submit" value="Log In!" class="button--pill"></p>
    </form>';

}
// Include footer
include('templates/footer.php');
?>

Now, I know the code is sloppy at best, and also I know its probably going to be insecure. This is just me getting the basics together, and have much to refine after the fact. But i've hit a brick wall. When I login via a user in the DB with the correct credentials, the logic works and the success message is displayed.. however so is this error:

Warning: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/src/templates/header.php:9) in /Applications/MAMP/htdocs/src/login.php on line 52

I've spent quite a bit of time on trying to resolve this both alone and in conjunction with a friend. I've googled the error and found a lot of resources claiming that this is due to output occurring before headers are sent. I've seen some claim that this caused by encoding. I've even seem some claim that a single white space after an include statement can cause this. To no avail, I tried everything. I'm using Sublime as my editor, and I verified the encoding to be correct on all files and in the Sublime default-user settings in the preferences file. I've verified that there are no white spaces after any include statements. I then sent my code to my friend who then simply copied my files into his existing project and on his machine he had no errors at all and my code worked as it should. I then had him send me back the same 3 files that we observed working flawlessly, and then copied them and overwrote my existing ones, yet still I get the above error.

I am using MAMP with PHP 7.1.6 and Apache. I've never had any issues like this before in the past, and have been writing PHP on this same machine and same setup for quite some time with no issues. Any advice to breakthrough this issue would be GREATLY appreciated! Thank you for your time.

DevOpsSauce
  • 1,319
  • 1
  • 20
  • 52
JDSchenck
  • 331
  • 1
  • 10
  • 1
    PHP already started sending the response back to the browser (client) in **header.php** so you can't use the `header()` function. – Spoody Apr 08 '18 at 23:08
  • "output started at /Applications/MAMP/htdocs/src/templates/header.php:9" –  Apr 08 '18 at 23:13
  • Yes I understand what the error is saying. However, I've tried meticulously to resolve it and no luck. For example the error is involving line 9 in header.php which is: How do I resolve this? – JDSchenck Apr 08 '18 at 23:15
  • _Yes I understand what the error is saying_ no you don't... check Obsidian's answer – Spoody Apr 08 '18 at 23:24
  • @MehdiBounya if this were the case, how does it explain running with 0 errors on an alternate LAMP server also with PHP 7.1? – JDSchenck Apr 08 '18 at 23:28
  • Maybe errors are not displayed. – Spoody Apr 08 '18 at 23:28

1 Answers1

0

Your include('templates/header.php'); on login.php will include all of the header.php page (including the HTML). You then call header() after that, which won't work, as header() must be called before anything is written to the DOM. Along this line, note that you can't print anything before header(); you'll need to move your // Page introduction as well.


I'd recommend creating a new file that you can include() at both relevant points, which only contains the session information, excluding any HTML. I'd also recommend turning header.php into an MVC view, only containing the presentation, rather than the logic.

session.php (a new file of any name):

<?php
session_start();
// Check and set the logged_in var
if (isset($_SESSION['username'])){
  $logged_in = true;
}else {
  $logged_in = false;
}?>

templates/header.php (a pure presentation page, with no logic):

<!DOCTYPE html> ....

login.php:

// Include session
include('session.php');

...
// Redirect to homepage, refreshes nav bar view
header('Location: index.php');
...

// Include header
include('templates/header.php');

// Page introduction
print '<h2>Login Form</h2>';

// Print page content
Obsidian Age
  • 41,205
  • 10
  • 48
  • 71