2

I am trying to learn PHP and I keep running into PHP errors. Here is a link to the site http://projects.jeremyohmann.com/homework. Would it be possible for someone to take a look at my code to see what I did wrong? I think the error is somewhere in head.php but it could also be in Login.php. The user keeps getting logged out right after a page refresh so I am assuming it has something to do with the php session.

The exact errors that I am getting are:

Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at /home/jeremyohmann/www/projects/homework/head.php:2) in /home/jeremyohmann/www/projects/homework/classes/Login.php on line 30

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /home/jeremyohmann/www/projects/homework/head.php:2) in /home/jeremyohmann/www/projects/homework/classes/Login.php on line 30

head.php

<html>
<?php 
require_once ('config/config.php');
require_once ('config/db.php');
require_once ('classes/Login.php');
$login = new Login(); ?>
<head>
<title>Homework Managment Project</title>
<link rel="stylesheet" type="text/css" href="reset.css">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<div id="wrapper">
<div id="header"><h1>Homework Management Project</h1></div>
<div id="nav">
<ul id="nav">
    <li><a href="index.php">Home</a></li>
    <li><a href="register.php">Register</a></li>
    <li><a href="about.php">About</a></li>
    <li><a href="classes.php">Classes</a></li>
    <?php 
    //ask is user is logged in.
    if($login->isUserLoggedIn()==true){
    //show this if the user is logged in.
    include('views/show-username.php');}
    else{
    //show this if the user isn't logged in.
    include('views/nav-login-form.php');}
    ?>
</ul>
</div>
<div id="content">

Login.php

<?php

/**
 * class Login
 * handles the user login/logout/session
 * 
 * @author Panique <panique@web.de>
 * @version 1.2
 */
class Login {

    private     $db_connection              = null;                     // database connection

    private     $user_name                  = "";                       // user's name
    private     $user_email                 = "";                       // user's email
    private     $user_password_hash         = "";                       // user's hashed and salted password
    private     $user_is_logged_in          = false;                    // status of login

    public      $errors                     = array();                  // collection of error messages
    public      $messages                   = array();                  // collection of success / neutral messages


    /**
     * the function "__construct()" automatically starts whenever an object of this class is created,
     * you know, when you do "$login = new Login();"
     */    
    public function __construct() {

        // create/read session
        session_start();                                        

        // check the possible login actions:
        // 1. logout (happen when user clicks logout button)
        // 2. login via session data (happens each time user opens a page on your php project AFTER he has sucessfully logged in via the login form)
        // 3. login via post data, which means simply logging in via the login form. after the user has submit his login/password successfully, his
        //    logged-in-status is written into his session data on the server. this is the typical behaviour of common login scripts.

        // if user tried to log out
        if (isset($_GET["logout"])) {

            $this->doLogout();

        } 
        // if user has an active session on the server
        elseif (!empty($_SESSION['user_name']) && ($_SESSION['user_logged_in'] == 1)) {

            $this->loginWithSessionData();                

        // if user just submitted a login form
        } elseif (isset($_POST["login"])) {

                $this->loginWithPostData();

        }        
    }    


    private function loginWithSessionData() {

        // set logged in status to true, because we just checked for this:
        // !empty($_SESSION['user_name']) && ($_SESSION['user_logged_in'] == 1)
        // when we called this method (in the constructor)
        $this->user_is_logged_in = true;

    }


    private function loginWithPostData() {

        // if POST data (from login form) contain non-empty user_name and non-empty user_password
        if (!empty($_POST['user_name']) && !empty($_POST['user_password'])) {

            // create a database connection, using the constants from config/db.php (which we loaded in index.php)
            $this->db_connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);

            // if no connection errors (= working database connection)
            if (!$this->db_connection->connect_errno) {

                // escape the POST stuff
                $this->user_name = $this->db_connection->real_escape_string($_POST['user_name']);            
                // database query, getting all the info of the selected user
                $checklogin = $this->db_connection->query("SELECT user_id,user_name, user_email, user_password_hash, first_name, last_name FROM users WHERE user_name = '".$this->user_name."';");

                // if this user exists
                if ($checklogin->num_rows == 1) {

                    // get result row (as an object)
                    $result_row = $checklogin->fetch_object();

                    // using PHP's crypt function to 
                    // this is currently (afaik) the best way to check passwords in login processes with PHP/SQL
                    if (crypt($_POST['user_password'], $result_row->user_password_hash) == $result_row->user_password_hash) {

                        // write user data into PHP SESSION [a file on your server]
                        $_SESSION['user_id'] = $result_row->user_id;
                        $_SESSION['user_name'] = $result_row->user_name;
                        $_SESSION['user_email'] = $result_row->user_email;
                        $_SESSION['first_name'] = $result_row->first_name;
                        $_SESSION['last_name'] = $result_row->last_name;
                        $_SESSION['user_logged_in'] = 1;

                        // set the login status to true
                        $this->user_is_logged_in = true; 

                    } else {

                        $this->errors[] = "Wrong password. Try again.";

                    }                

                } else {

                    $this->errors[] = "This user does not exist.";
                }

            } else {

                $this->errors[] = "Database connection problem.";
            }

        } elseif (empty($_POST['user_name'])) {

            $this->errors[] = "Username field was empty.";

        } elseif (empty($_POST['user_password'])) {

            $this->errors[] = "Password field was empty.";
        }           

    }

    /**
     * perform the logout
     */
    public function doLogout() {

            $_SESSION = array();
            session_destroy();
            $this->user_is_logged_in = false;
            $this->messages[] = "You have been logged out.";     

    }

    /**
     * simply return the current state of the user's login
     * @return boolean user's login status
     */
    public function isUserLoggedIn() {

        return $this->user_is_logged_in;

    }

}

index.php

<?php include('head.php') ?>
<p>This is the test site for the Homework Grade Checker... Please check back soon to see if more progress has been made.</p>
<?php include('foot.php') ?>
ASGM
  • 11,051
  • 1
  • 32
  • 53
user2363217
  • 695
  • 1
  • 7
  • 15
  • 1
    Googling the error you got comes up with a plethora of excellent information... `Cannot send session cookie - headers already sent by`. Which is why I voted to close this question. – Jasper May 08 '13 at 16:55
  • because session_start(); has already started. check your other file config.php and db.php – tonoslfx May 08 '13 at 16:56
  • If none of the solutions in this questions worked for you, please check at the very beginning of your php files if there are spaces or hidden special characters because they also count as "output" and thus your `session_start()` would fail **even if there is a single space** `­ ­` before the ` – Beyondo Jul 12 '22 at 11:51

2 Answers2

5

You can't start a session after you've sent output to the browser.. Put the <html> tag above the <head> tag.

<?php 
require_once ('config/config.php');
require_once ('config/db.php');
require_once ('classes/Login.php');
$login = new Login(); ?>
<html>
<head>
Madbreaks
  • 19,094
  • 7
  • 58
  • 72
1

Functions that send/modify HTTP headers must be called before any output to the browser is made otherwise you'll get the error:

Warning: Cannot modify header information - headers already sent (output started at file:line)

This error will tell you which file is causing the problem and on what line.

Your starting a session after the <html> tag. So make the following change and you'll be fine.

<?php 
require_once ('config/config.php');
require_once ('config/db.php');
require_once ('classes/Login.php');
$login = new Login(); 
?>
<html>
<head>
ajtrichards
  • 29,723
  • 13
  • 94
  • 101