Domanda

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') ?>
È stato utile?

Soluzione

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>

Altri suggerimenti

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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top