1

INTRO: FIRST: I Know about How to fix "Headers already sent" error in PHP

My question isn't about why it doesn't work. I know why it doesn't work, there is output before header();. My question is why it works for a guy in a YT video, that I am learning from, when he has the same output before header();

POST: I am a super noob PHP programmer, self-learning for just a few weeks. I am trying to do a login system with PHP, learning from a youtube video. I got an error

Cannot modify header information - headers already sent by (output started at Sites/Login/inc/header.php:5...

and I think I know why I got the error.

My code:

index.php

<?php
require_once("inc/header.php");
?>
<?php
    if (func::checkLoginState($conn))
    {
        echo "Welcome" . $_SESSION["username"] . "!";
    } else
    {
        header("location:login.php");
    }
?>

<?php
require_once("inc/footer.php");
?>

functions.php (Short version, so it returns false)

<?php
class func {
    public static function checkLoginState ($conn)
    {
        return false; 
    }
}
?>

header.php

<?php
include_once("config/config.php");
include_once("functions.php");
?>
<html>
    <head>
        <title>Login project</title>
    </head>
    <body>

config.php contains just PDO database connection setup

footer.php closing HTML tags

Now, if I delete HTML tags from header.php, the header(); function works. What I can't for the life of me figure out is, why it works for the guy, who I am learning from in the youtube video (he HAS the html tags in header.php).

at 4:30 you can see his header.php

at 6:58 you can see his index.php (He actually has html code in this file before header(); and at 7:15 it just works..)

at 7:15 you can see index.php in the browser, it doesn't throw an error and redirects him to login.php

https://youtu.be/3xdxhfNg3Xg?t=4m30s

He HTML tags in the header.php as well and he includes it before the if the function in index.php. I have exactly the same code basically. Just to shorten it, I returned false in my checkLoginState function, so it does the else part in the function in index.php. He doesn't use ob_start(); anywhere (which is supposed to solve this somehow).

It's probably some basic thing that I missed but it bugs me so much. Thank you for clarifying this. Also, how am I supposed to redirect to login.php, since header(); seems kinda useless?

Thank you and have a great day!

Dejw
  • 23
  • 3

4 Answers4

2

that error only occurs when something is sent back to the browser before you try to send headers.

You have multiple php tags at the top of your page, there's white space between them. Also, you are sending text back in your header file.

copying your code straight out of your post, there is a space between your 2 sets of tags on line 3 after the ?>.

1. <?php
2. require_once("inc/header.php");
3. ?> 
4. <?php

you dont need to open and close php tags around those lines.

<?php
    session_start();  // start the session here so you dont forget

    if (func::checkLoginState($conn))
    {
        require_once("inc/header.php");  // only include your top html template if you know you are good to go
        echo "Welcome" . $_SESSION["username"] . "!";
    } else
    {
        header("location:login.php");
    }

    require_once("inc/footer.php");
?>

this is perfectly fine.

edit based on your comments

youtube videos can be edited any way he wants it. If you forward to the end, hes removed the header redirect and put in a login form. So I would bet it wasnt working for him either.

DevDonkey
  • 4,835
  • 2
  • 27
  • 41
  • Yeah, it's written in this way because I might add some html before the if function, like a
    or something. But that doesn't seem to be the problem, the problem is html code in header.php. As I understand it, it can't be there? But the guy in the video has it there. That is my question, why it works for him and not for me.
    – Dejw Sep 18 '18 at 07:43
  • 1
    it cant possibly work if you send text back to the browser first. – DevDonkey Sep 18 '18 at 07:44
  • Look at his video https://youtu.be/3xdxhfNg3Xg?t=4m30s. He has html tags in header.php. at 4:30 you can see his header.php at 6:58 you can see his index.php at 7:15 you can see index.php in the browser, it doesn't throw an error and redirects him to login.php. My question is HOW. How can he have html in header.php, he includes header.php at the start of index.php (that is before the header();) and it just frickin works. I want it to work for me too. – Dejw Sep 18 '18 at 07:50
  • updated my answer based on watching the (poor) video – DevDonkey Sep 18 '18 at 07:55
  • 1
    What makes you so sure that his code actually works correctly? At 7:15 it shows an error message "This page isn't redirecting correctly" – Barmar Sep 18 '18 at 07:55
  • He literally has html code before the header(); in the index.php... – Dejw Sep 18 '18 at 07:56
  • I wouldn't use that video as a model, he's apparently storing plaintext passwords in his database. – Barmar Sep 18 '18 at 07:56
  • @Barmar that's because he's redirecting to login.php that is redirecting again, he fixed that at around 7:05 – Dejw Sep 18 '18 at 07:57
  • @DevDonkey ok, so you're saying it didn't work for him with the html in header.php and index.php and he edited it so it showed it worked. Well since the video is poor, as you said, I highly doubt he cut it or edited it, since he's made a few mistakes on the video, that he actually corrected on the video. If he edited it, why wouldn't he edit the mistakes he's made.. – Dejw Sep 18 '18 at 08:06
  • fact is, his code cant possibly work with text going back before the header call. How he fudged it to look like it worked we'll never know. – DevDonkey Sep 18 '18 at 08:12
  • @DevDonkey Also, if we don't figure out why it works for him, how do I do the function correctly? basically if someone lands on index.php and he isn't logged in, how do I redirect him to login.php? Thanks. :) I can include config.php and functions.php separetely from header.php and before I include the header.php call the if function and thus header(); would work I guess, because it would be before the html and whitespace, but is there a better solution? – Dejw Sep 18 '18 at 08:17
0

Why we get this type error

Cannot modify header information - headers already sent by
  1. New line characters or spaces are before <?php

Solution: Remove everything before <?php

  1. BOM (Byte-Order-Mark ) in utf-8 encoded PHP files

Solution: Change the file encoding to "without BOM" (e.g. using notepad++) or remove the BOM before

  1. Echo before header

    Solution: RemoveRemove the echo before header Use ob_start(); and ob_end_flush(); for buffered output

Reference

Gufran Hasan
  • 8,910
  • 7
  • 38
  • 51
0

You can use output buffering control to prevent header being sent out prematurely. The video you reference probably used it. Or else he has to use it to make it functional.

For example,

<?php

ob_start(); // start buffering all "echo" to an output buffer

?>
<html>

<?php

if (func::checkLoginState()) {
    echo "Login";
} else {
    header('Location: /login.php');
}

?>

</html>

<?php ob_end_flush(); ?>

The function ob_start can be put into header.php or config. The function call ob_end_flush can be put into the footer, or totally omit it.

Since all output are written to output buffer, and not directly to the browser, you can use header call after any echo, but before ob_end_flush.

Koala Yeung
  • 7,475
  • 3
  • 30
  • 50
  • Thank you, maybe that's how he's doing it, but I couldn't find the ob_start anywhere in his files, I looked for it. But it's possible he edited the video, as DevDonkey said in comments to his post. I will try this ob_start thing so the header(); works :) thanks – Dejw Sep 18 '18 at 08:41
0

So to sum up we couldn't figure out, why it works for the guy in the video. Thank you everyone for trying to figure it out. Theories are:

  1. He edited to video so it seemed it worked with this version of the code
  2. There is and ob_start(); and ob_end_flush(); somewhere in the code and it isn't visible in the video
Dejw
  • 23
  • 3