Yritin tehdä jonkinlaisen foorumin tämän vinkin avulla. Lisäsin siihen topicit, mutta sen jälkeen viestit eivät enää tulostuneet ruudulle. Koodi:
<?php try { session_start(); if(!isset($_SESSION["id"])) { header("Location: signin.php?returnurl={$_SERVER["PHP_SELF"]}"); die(); } else if(isset($_SESSION["aika"])) { if($_SESSION["aika"] + 1800 < time()) { header("Location: signin.php?returnurl={$_SERVER["PHP_SELF"]}"); die(); } } $_SESSION["aika"] = time(); class foorumi { private $topicit; public function __construct() { $this->topicit = file("topicit.txt"); } public function etusivu() { ?> <p>Valitse selattava topic alta.</p> <table> <?php foreach($this->topicit as $topic) { $tiedot = explode("|", $topic); echo "<tr><td><a href=\"testforum.php?tapahtuma=lue&t={$tiedot[0]}\">{$tiedot[1]}</a></td></tr>"; } echo "</dl>"; } public function hae() { if (!file_exists("viestit.txt")) { if (!file_put_contents("viestit.txt", serialize(array()), LOCK_EX)) { trigger_error("Tiedoston luonti ei onnistu!", E_USER_ERROR); } } $viestit = unserialize(file_get_contents("viestit.txt")); return $viestit; } public function lue($viestit, $topicid) { ?> <p><a href="testforum.php?tapahtuma=lomake&t=<?php echo $topicid ?>">Uusi viesti</a></p> <?php if(!empty($viestit)) { foreach ($viestit as $id => $viesti) { if($viesti["topicid"] == $topicid) { $nimi = htmlspecialchars($viesti["nimi"]); $aika = htmlspecialchars($viesti["aika"]); $viesti = nl2br(htmlspecialchars($viesti["teksti"])); echo "<p><a name='{$id}'><small>#{$id}:</small></a><br />{$nimi}"; echo " (" . date("d.m.Y H:i", $aika) . "):<br />"; echo "{$viesti}</p><hr />"; } } } else { echo "<p>Tässä topicissa ei ole viestejä!</p>"; } ?> <p><a href="#up">Takaisin ylös</a></p> <?php } public function laheta($nimi, $topicid, $teksti) { $viestit = $this->hae($topicid); end($viestit); $id = key($viestit) + 1; $viestit[$id] = array( "nimi" => $nimi, "aika" => time(), "topicid" => $topicid, "teksti" => $teksti, ); if (!file_put_contents("viestit.txt", serialize($viestit), LOCK_EX|FILE_APPEND)) { trigger_error("Tallennus ei onnistu!", E_USER_ERROR); } $sivu = "testforum.php?tapahtuma=lue&t={$topicid}"; header("Location: {$sivu}#{$id}"); die(); } public function lomake($topicid) { $kayttajat = file("kayttajat.txt"); foreach($kayttajat as $kayttaja) { $tiedot = explode("|", $kayttaja); if($tiedot[0] == $_SESSION["id"]) { $nimi = $tiedot[1]; break; } } ?> <form action="?tapahtuma=laheta" method="post"> <input type="hidden" name="nimi" value="<?php echo $nimi ?>" /> <p>Viestisi: <br /><textarea name="teksti" rows="15" cols="60"></textarea></p> <input type="hidden" name="topicid" value="<?php echo $topicid ?>" /> <button type="submit">Lähetä</button> </form> <?php } } $foorumi = new foorumi(); include("yla.php"); if(isset($_GET["tapahtuma"])) { $tapahtuma = $_GET["tapahtuma"]; } else { $tapahtuma = "etusivu"; } if($tapahtuma == "etusivu") { $foorumi->etusivu(); } else if($tapahtuma == "lue") { $foorumi->lue($foorumi->hae(), $_GET["t"]); } else if($tapahtuma == "lomake") { $foorumi->lomake($_GET["t"]); } else if($tapahtuma == "laheta") { $foorumi->laheta($_POST["nimi"], $_POST["topicid"], $_POST["teksti"]); } else { throw new Exception("Tuntematon tapahtuma: " . $tapahtuma . "!"); } include("ala.php"); } catch(Exception $p) { die("Poikkeus: " . $p->getMessage()); } ?>
Käyttäjä on aiemmin jo kirjautunut sivulle.
Kayttajat.txt on muotoa:
viesti-id|nimi|salasana(kryptattu)
Ja topicit.txt:
topicid|topicin nimi
Tietääkö joku, mitä tehdä?
Olet lisännyt omin päin tiedoston kirjoitukseen valitsimen FILE_APPEND. Ota se pois. Koodivinkissä tiedosto luetaan aina kokonaan ja tallennetaan aina kokonaan. Kun lisäät ylimääräistä dataa tiedoston loppuun, datan purkaminen (unserialize) ei enää onnistu. Jos lukisit virheilmoituksia, varmaan tietäisit tämänkin jo. Pidä aina kaikki virheilmoitukset näkyvissä, kun koodaat.
Lisäksi koodisi on pullollaan muita pieniä virheitä ja tietoturva-aukkoja. Laita virheilmoitukset ja varoitukset näkyviin, korjaa lukuisat XSS-aukot ja validoi sivujen HTML-koodi.
No nytpä näyttää toimivan.
Edit: Ei muuten tule edes noita Notice-tason ilmoituksia...
Jos virheviestit eivät tulostu niin voit koittaa laittaa koodin alkuun funktion error_reporting
. Se määrittää mitkä virheet näytetään.
Esimerkki:
// Näytä kaikki virheet error_reporting(E_ALL); // Älä näytä virheitä // (Suositeltavaa julkisilla sivuilla) error_reporting(0);
Lue lisää PHP:n manuaalista.
Virheraportointi on kyllä hyvä pitää päällä tuotannossakin (ns. julkiset sivut), koska muutoinhan virheiden syy ja kriittisyys voi olla hyvin vaikeaa selvittää jälkikäteen. On eri asia kieltää virheiden tulostaminen käyttäjälle kuin ottaa virheraportointi pois päältä. Virheiden julkinen tulostus estetään asetuksella display_errors = 0.
Aihe on jo aika vanha, joten et voi enää vastata siihen.