[PHP] Header("Location: ...") & ob_start()

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Carharttguy
  • Registratie: Juli 2010
  • Laatst online: 23-04 18:36
Dag iedereen

Ik ben en website aan het samensteken, en gebruik daar vaak de Header() function waarbij ik de gebruiker doorstuur naar een andere locatie. Dit werkte op mijn lokale wampserver heel goed. Maar heb nu een shared hosting account, waar denk ik apache op draait. En dat werkt precies wat anders.

Ik kreeg de volgende fout:
Warning: Cannot modify header information - headers already sent by ...
Ik heb die fout opgezocht, en ik snap waarom ze zich voordoet, een mogelijke oplossing leek de functie ob_start() te zijn, die alle data buffert en dan ineens stuurt.

Dit werkt, maar als ik de gebruiker van de de loginpagina naar de homepagina stuur, zijn mijn menu's en dergelijke niet aangepast naar die van een ingelogde gebruiker. Als ik F5 doe gebeurt er niets. Als ik CTRL+F5 doe, dan wordt alles aangepast, en zie ik dat ik ingelogd ben. (En dus dat de sessie goed werkt)

Is ob_start() de juiste oplossing? En wat doe ik fout met die location header? Want mijn browser lijkt die refresh niet goed door te krijgen, en toont gewoon een gecachete pagina.

Hartelijk dank om mee te denken

Acties:
  • 0 Henk 'm!

  • royduin
  • Registratie: November 2007
  • Laatst online: 18:21
Je moet ervoor zorgen dat de header() functie gebruikt voordat je iets output, ofwel:

Fout:
PHP:
1
2
echo 'Je wordt doorgestuurd...';
header('Location: http://www.example.com/');


Goed:
PHP:
1
2
header('Location: http://www.example.com/');
echo 'Je wordt doorgestuurd...';


Op die manier krijg je geen foutmelding. Dus er dient nog geen output te zijn voordat je de header functie aanspreekt (ook geen <!doctype html><html>,enz..)

[ Voor 43% gewijzigd door royduin op 30-07-2014 13:43 ]


Acties:
  • 0 Henk 'm!

  • FotW
  • Registratie: Juli 2012
  • Laatst online: 22-04 14:23
Ik had hetzelfde euvel met een javascript reload gisteren, daar kun je echter een parameter meegeven die forceert dat de pagina opnieuw opgehaald wordt ( location.reload(true) ). Nou weet ik niet of php iets soortgelijks heeft, maar wat je zou kunnen proberen is je url aanvullen met een GET parameter met daarin bijvoorbeeld een timestamp. Wellicht dat dat de pagina forceert om niet de gecachete versie te gebruiken.

Acties:
  • 0 Henk 'm!

  • royduin
  • Registratie: November 2007
  • Laatst online: 18:21
FotW schreef op woensdag 30 juli 2014 @ 13:45:
Ik had hetzelfde euvel met een javascript reload gisteren, daar kun je echter een parameter meegeven die forceert dat de pagina opnieuw opgehaald wordt ( location.reload(true) ). Nou weet ik niet of php iets soortgelijks heeft, maar wat je zou kunnen proberen is je url aanvullen met een GET parameter met daarin bijvoorbeeld een timestamp. Wellicht dat dat de pagina forceert om niet de gecachete versie te gebruiken.
Carharttguy schreef op woensdag 30 juli 2014 @ 13:32:
waarbij ik de gebruiker doorstuur naar een andere locatie.
Volgens mij niet waar Carharttguy naar op zoek is.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 23:33
royduin schreef op woensdag 30 juli 2014 @ 13:47:
[..]
Volgens mij niet waar Carharttguy naar op zoek is.
Nou, het lijkt er wel op dat de pagina nog in de cache staat
Als ik F5 doe gebeurt er niets. Als ik CTRL+F5 doe, dan wordt alles aangepast, en zie ik dat ik ingelogd ben
Wat gezegd wordt over header() en dat dat voordat je content stuurt, verzonden moet worden, klopt. Maar als je ook met F5 nog de oude pagina krijgt, lijkt het erop dat je pagina in de cache blijft staan.
Dat kan je eenvoudig zien met Chrome Developer Tools (of Firebug/IE tools), bij je Network tab zie je of de response uit de cache komt, of vers opgehaald wordt. Als je op ctrl+f5 drukt, zie je dan als het goed is dat je een 'verse' response krijgt, en dan zie je ook de headers die meegezonden worden. Het kan zijn dat daarin meegezonden wordt dat hij pas over een maand (of dag/uur) expired. Dan bewaart je browser de reactie tot die tijd.

Dat zou je kunnen oplossen door correct Expire headers mee te sturen (ofwel in PHP, of met htaccess, zoals hier: https://github.com/h5bp/h...lob/master/.htaccess#L647)

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Als je iemand doorstuurt met header('Location: ...');, gooi er dan ook meteen een exit; achteraan:

PHP:
1
2
header('Location: http://nu.nl');
exit;

Acties:
  • 0 Henk 'm!

  • Sgreehder
  • Registratie: Juni 2004
  • Laatst online: 04-03 18:20
HuHu schreef op woensdag 30 juli 2014 @ 14:13:
Als je iemand doorstuurt met header('Location: ...');, gooi er dan ook meteen een exit; achteraan:

PHP:
1
2
header('Location: http://nu.nl');
exit;
Zowel exit() als de eindtag zijn bijzonder overbodig, zeker in dit voorbeeld.

Met betrekking tot de TS, stuur de volgende header ook mee:

code:
1
2
<?php
header('Cache-Control: no-cache');


Zie ook:

http://www.mobify.com/blo...de-to-http-cache-headers/

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Sgreehder schreef op donderdag 31 juli 2014 @ 08:38:
[...]


Zowel exit() als de eindtag zijn bijzonder overbodig, zeker in dit voorbeeld.
Waarom?

Acties:
  • 0 Henk 'm!

  • orf
  • Registratie: Augustus 2005
  • Laatst online: 23:34

orf

Sgreehder schreef op donderdag 31 juli 2014 @ 08:38:
[...]


Zowel exit() als de eindtag zijn bijzonder overbodig, zeker in dit voorbeeld.
Als je iemand wil verbeteren, moet je wel zeker weten dat je het echt beter weet.

Script executie stopt niet door een header(). De exit is dus zeker wel nodig als je niet wilt dat de code onder de header uitgevoerd wordt.

Voorbeeld uit de documentatie:
PHP:
1
2
3
4
5
6
<?php
header("Location: http://www.example.com/"); /* Redirect browser */

/* Make sure that code below does not get executed when we redirect. */
exit;
?>

http://php.net/manual/en/function.header.php

[ Voor 14% gewijzigd door orf op 31-07-2014 08:44 ]


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Sgreehder schreef op donderdag 31 juli 2014 @ 08:38:
[...]


Zowel exit() als de eindtag zijn bijzonder overbodig, zeker in dit voorbeeld.

Met betrekking tot de TS, stuur de volgende header ook mee:

code:
1
2
<?php
header('Cache-Control: no-cache');


Zie ook:

http://www.mobify.com/blo...de-to-http-cache-headers/
:')

De exit na een header met location is zeker wel nodig. De door jou gegeven link gaat over cache headers, niet relevant dus.

Daarnaast had je prima kunnen zien, toen je me quotte, dat Tweakers de begin en eind tags automatisch eromheen heeft gezet.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 23:33
HuHu schreef op donderdag 31 juli 2014 @ 08:52:
[...]

:')

De exit na een header met location is zeker wel nodig. De door jou gegeven link gaat over cache headers, niet relevant dus.
Die cache link ging over het daadwerkelijke probleem, dat de inhoud gecached werd ;)

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 23-04 16:41

drm

f0pc0dert

Als je een 301 status code meegeeft zijn er browsers die hardnekkig cachen. Terecht, want het betekent immers "Moved Permanently", maar niet altijd handig als je wilt testen. Incognito browsen biedt uitkomst.

Geen idee of dat je probleem is, maar toch handig om te weten.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Barryvdh schreef op donderdag 31 juli 2014 @ 08:57:
[...]

Die cache link ging over het daadwerkelijke probleem, dat de inhoud gecached werd ;)
Oeps... te snel gelezen *O*

Acties:
  • 0 Henk 'm!

  • Sgreehder
  • Registratie: Juni 2004
  • Laatst online: 04-03 18:20
drm schreef op donderdag 31 juli 2014 @ 20:30:
Als je een 301 status code meegeeft zijn er browsers die hardnekkig cachen. Terecht, want het betekent immers "Moved Permanently", maar niet altijd handig als je wilt testen. Incognito browsen biedt uitkomst.

Geen idee of dat je probleem is, maar toch handig om te weten.
Hmm, goed punt. Probeer anders ook:

code:
1
header('Location: ' . $url , true, 302);


302 = Moved Temporarily

Acties:
  • 0 Henk 'm!

  • Carharttguy
  • Registratie: Juli 2010
  • Laatst online: 23-04 18:36
Dank jullie wel voor alle jullie raad en voorbeelden.
Echter, ik raak geen meter verder. Ik gebruik dus een index pagina met Include om daarin bijvoorbeel een loginpagina te tonen. Zie hieronder de indexpagina:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
    ob_start();
    session_start();
    include_once("database.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<link rel="stylesheet" type="text/css" href="mainstyle.css"/>
<link rel="stylesheet" type="text/css" href="productstyle.css"/>

<head>
    <title>mijntitel</title>
</head>
<body>
    <div id="website">
        <div id="header">
        </div>
        <div id="menu">
            <ul>
        <?php
            if(!isset($_SESSION['email'])){
                echo "<li id='MenuImageHome'><a href='/index.php?pag=home'>Home</a></li>";
                echo "<li id='MenuImageInloggen'><a href='/index.php?pag=inloggen'>Inloggen</a></li>";
                echo "<li id='MenuImageRegistreren'><a href='/index.php?pag=registreren'>Registreren</a></li>";
            }else{
                echo "<li id='MenuImageHome'><a href='/index.php?pag=home'>Nieuws</a></li>";
                echo "<li id='MenuImageProducten'><a href='/index.php?pag=producten'>Producten</a></li>";
                echo "<li id='MenuImageAccount'><a href='/index.php?pag=account'>Account</a></li>";
                if(isset($_SESSION['productid'])){
                    echo "<li id='MenuImageWinkelmandje'><a href='/index.php?pag=winkelmandje'>Winkelmandje (<b>".count($_SESSION['productid'])."</b>)</a></li>";
                }else{
                    echo "<li id='MenuImageWinkelmandje'><a href='/index.php?pag=winkelmandje'>Winkelmandje</a></li>";
                }
                echo "<li id='MenuImageUitloggen'><a href='/index.php?pag=uitloggen'>Uitloggen</a></li>";
            }
        ?>
            </ul>
        </div>
        <div id="content">
            <?php
            if(isset($_GET['pag'])){
                switch($_GET['pag']){
                    case "home":
                        include_once("home.php");
                        break;
                    case "inloggen":
                        include_once("inloggen.php");
                        break;
                    case "registreren":
                        include_once("registreren.php");
                        break;
                    case "producten":
                        include_once("producten.php");
                        break;
                    case "account":
                        include_once("account.php");
                        break;
                    case "productdetail":
                        include_once("productdetail.php");
                        break;
                    case "voegtoeaanwinkelmandje":
                        include_once("voegtoeaanwinkelmandje.php");
                        break;
                    case "verwijderenvanwinkelmandje":
                        include_once("verwijderenvanwinkelmandje.php");
                        break;
                    case "winkelmandje":
                        include_once("winkelmandje.php");
                        break;
                    case "uitloggen":
                        include_once("uitloggen.php");
                        break;
                    default:
                        include_once("home.php");
                }
            }else{
                echo "home pagina";
            }
            ?>
        </div>
        <div id="footer">
            whatever
        </div>
    </div>
</body>
</html>
<?php
    ob_end_flush();
?>


Let op de ob_* functies die ik gebruik.

Hieronder dan een voorbeeld van de loginpagina:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<form action="index.php?pag=inloggen" method="post">
    <h3>Inloggen:</h3>
<?php
    include_once("database.php");
    if(isset($_POST['inloggen'])){
        $escapedemail = mysql_real_escape_string($_POST['email']);
        $query = "SELECT * FROM klanten WHERE email = '".$escapedemail."'";
        $resultaat = mysql_query($query);
         
        if(mysql_num_rows($resultaat) == 1){
            $hashedensaltedwachtwoord = hash('sha256', $_POST['wachtwoord'].mysql_result($resultaat, "0", "salt"));
            $wachtwoord = mysql_result($resultaat, "0", "wachtwoord");
            
            if($hashedensaltedwachtwoord == $wachtwoord){
                $_SESSION['email'] = $escapedemail;
                header('Location: http://foo.foo/index.php?pag=home, true, 302');
                exit;
            }else{
                echo '<font color="red">Het ingevoerde wachtwoord is onjuist.</font><br />';
            }
        }else{
            echo '<font color="red">Het ingevoerde emailadres is onjuist.</font><br />';
        }
    }
?>
Email:<br />
<input id="registrereninput" type="text" name="email" /><br />
Wachtwoord:<br />
<input id="registrereninput" type="password" name="wachtwoord" /><br />
<input id="knop" name="inloggen" type="submit" value="Inloggen!" /></form>


Let niet op lelijke en verouderde code. Het punt is dat ik nu
header('Location: http://foo.foo/index.php?pag=home, true, 302');
verstuur, en dat werkt, de pagina wordt gewoon doorgestuurd. Maar zoals je in de indexpagina kan zien, moeten bepaalde links veranderen bij het inloggen, dat gebeurt allemaal niet. Maar na een CTRL+F5 wel.

Als iemand een idee heeft wat ik verkeerd doe, stel ik het heel hard op prijs om me de juiste richting in te duwen!

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Je ' staat op de verkeerde plek:

PHP:
1
header('Location: http://foo.foo/index.php?pag=home', true, 302);

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 23:33
Heb je nou naar je cache /expire headers gekeken?

Acties:
  • 0 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 23:43
Je output ook al een <form> en <h3> tag voor de header.

Deze zul je moeten verplaatsen dus... En daarvoor moet je dus even je if-structuur omgooien. Eerlijk gezegd zou ik de hele inlog eerst checken en dan pas verder laten gaan en eventueel het inlog formulier printen.

Het zou zo kunnen:


PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
    include_once("database.php");
    if(isset($_POST['inloggen'])) {
        $escapedemail = mysql_real_escape_string($_POST['email']);
        $query = "SELECT * FROM klanten WHERE email = '".$escapedemail."'";
        $resultaat = mysql_query($query);
         
        if(mysql_num_rows($resultaat) == 1){
            $hashedensaltedwachtwoord = hash('sha256', $_POST['wachtwoord'].mysql_result($resultaat, "0", "salt"));
            $wachtwoord = mysql_result($resultaat, "0", "wachtwoord");
            
            if($hashedensaltedwachtwoord == $wachtwoord) {
                $_SESSION['email'] = $escapedemail;
                header('Location: http://foo.foo/index.php?pag=home, true, 302');
                exit;
            }
            else {
               $error = "Wachtwoord incorrect";
            }
        }
        else {
           $error = "E-mail incorrect";
        }
    }
?>

<html>
    <head>
        <titlle>Whatever</title>
    <head>
    <body>
        <div id="error"><?=$error?></div>
        <form action="index.php?pag=inloggen" method="post">
            <h3>Inloggen:</h3>
            Email:<br />
            <input id="registrereninput" type="text" name="email" /><br />
            Wachtwoord:<br />
            <input id="registrereninput" type="password" name="wachtwoord" /><br />
            <input id="knop" name="inloggen" type="submit" value="Inloggen!" /></form>
        </form>
    </body>
</html>


P.S. Ik zou alleen zeggen dat inlog incorrect is; nu kunnen users in principe e-mail adressen gaan brute forcen. Opmaak van de error kan via CSS op error div.

[ Voor 137% gewijzigd door Morrar op 02-08-2014 00:29 ]


Acties:
  • 0 Henk 'm!

  • Carharttguy
  • Registratie: Juli 2010
  • Laatst online: 23-04 18:36
HuHu schreef op vrijdag 01 augustus 2014 @ 18:57:
Je ' staat op de verkeerde plek:

PHP:
1
header('Location: http://foo.foo/index.php?pag=home', true, 302);
Thanks, inderdaad.
Barryvdh schreef op zaterdag 02 augustus 2014 @ 00:09:
Heb je nou naar je cache /expire headers gekeken?
Heb ik gedaan, ik krijg het vermoeden dat het niet met mijn script heeft te maken, maar met een programma genaamd Varnish, zie hieronder de headers die ik zie in Tamper data:
Afbeeldingslocatie: http://i.imgur.com/Wyia13f.png
Dankje om ernaar te kijken.
Morrar schreef op zaterdag 02 augustus 2014 @ 00:17:
Je output ook al een <form> en <h3> tag voor de header.

Deze zul je moeten verplaatsen dus... En daarvoor moet je dus even je if-structuur omgooien. Eerlijk gezegd zou ik de hele inlog eerst checken en dan pas verder laten gaan en eventueel het inlog formulier printen.

Het zou zo kunnen:


PHP:
1
..code..


P.S. Ik zou alleen zeggen dat inlog incorrect is; nu kunnen users in principe e-mail adressen gaan brute forcen. Opmaak van de error kan via CSS op error div.
Je hebt gelijk over de code, maar de pagina wordt geïnclude in een andere pagina, dus staat er eigenlijk sowieso HTML code boven.

En over die email adressen, goed punt, onmiddellijk veranderd. Dankje!

Acties:
  • 0 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 23:43
Ok, daar had ik even overheen gelezen. Eigenlijk zou ik je sowieso aanraden om logica en output te scheiden, bijvoorbeeld door het gebruik van templates. Zelf vind ik Smarty bijvoorbeeld een aardige template engine: http://www.smarty.net/. Daarmee kun je eenvoudig de HTML scheiden van de PHP code.

Maar als je het door elkaar wilt laten, dan kan dat ook. Alleen is een ob_start() dan niet afdoende. Je moet die output buffer dan wel wegdonderen voor je header met ob_end_clean(). Zie ook: http://stackoverflow.com/...n-php-when-using-ob-start.

Hopelijk helpt dat!

P.S. Eventueel kun je header_sent() gebruiken om te zien waar de headers gestuurd werden: http://docs.php.net/headers_sent

[ Voor 10% gewijzigd door Morrar op 02-08-2014 16:22 ]


Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 23:33
Of Twig, dat vind ik persoonlijk wel fijn.

Maar Varnish is een cache, die tussen php en de browser zit, maar dan zou je met de goede headers kunnen instellen dat hij niet gecached wordt. Wel vreemd dat dat aanstaat als je het zelf niet weet.
Pagina: 1