Alweer een vraag? Ja, helaas of gelukkig wel. Kan ik jullie kennis wederom aanspreken.

Ik heb een formulier, dat roept een php aan. Werkt goed. Maar nu wil ik vermijden dat een gebruiker deze laatste pagina refreshed, F5 of Ctrl F5. Ik heb gelezen dat je met unset $_POST iets kunt doen. Nou dat werkt niet.

Ik check if($_SERVER['REQUEST_METHOD']=="POST") {

Wat is jullie ervaring om dit op te lossen? Want elke refresh voegt de gegevens toe aan de database. Dus vervelend. Is dat op de lossen?
Dat POST-Redirect-GET ga ik proberen. Dank
Dat is inderdaad wat je zou moeten doen. Post/Redirect/Get voorkomt ook het dubbelposten-door-terug-te-navigeren omdat je meteen na de verwerking van het formulier redirect. Navigeer je in zo'n opzet terug na versturen van het formulier kom je weer uit bij het formulier.

Neemt niet weg dat extra voorzieningen nodig kunnen zijn, zoals een CSRF-token (een token om cross site request forgeries, oftewel het posten van informatie vanaf een andere website, te voorkomen). Als het formulier al afgeschermd is door een login is dit trouwens niet per se nodig, maar het kan handig zijn om je formulieren standaard uit te rusten met deze functionaliteit.

Ook kan het handig zijn om een soort van validatie-routines te schrijven die alles controleren voordat je het formulier daadwerkelijk verwerkt. En het zou helemaal mooi zijn als je dan het formulier opnieuw inlaadt met de reeds ingevulde informatie en aangeeft wat hier aan mankeert.

Zorg ook dat alle verschillende acties apart worden gecompartimenteerd, ofwel:
- het tonen van het formulier
- het verwerken van het formulier
- het tonen van enige succesboodschap (of een flash message op een overzichtspagina kan ook afdoende zijn)

Dit om te voorkomen dat je code één grote if-elseif-else-brei wordt.

Manieren om deze acties te splitsen zijn:
- stop ze alle in aparte bestanden (maar dit kan bewerkelijk zijn)
- stop ze alle in aparte methoden van een klasse
- andere? (ik zou niet teruggaan naar normale functies maar proberen om in de OOP-richting te sturen)

Doordat je de acties scheidt is het wel nodig om op een of andere manier informatie over te hevelen tussen "pagina's". Als je dus iemand terugstuurt naar de toon-het-formulier-actie met reeds eerder ingevulde informatie zul je deze data op een of andere manier moeten transporteren, bijvoorbeeld via de sessie.

NB een (session) flash message is een boodschap die eenmalig op het scherm getoond wordt en daarna meteen wordt gewist uit de sessie. Dit zou je bijvoorbeeld in je maintemplate kunnen opnemen, ik maar hier zelf in het backend ook gebruik van. Op die manier kun je met minimale middelen overbrengen dat een actie (die geen echte output heeft zoals het toevoegen, wijzigen of verwijderen van een item) is geslaagd. Zo zit deze snippet in mijn admin maintemplate:
<?php
if (empty($_SESSION['messages']) === false) {
    ?><div id="messages"><?php
        foreach ($_SESSION['messages'] as $index => $message) {
            ?><div class="<?php echo $this->escape($message['type']) ?>"><?php
                // It is the programmers responsibility to escape these messages on input as they may contain HTML.
                echo $message['message'];
            ?></div><?php
        }
        $_SESSION['messages'] = array();
        // @todo think of a way to make notifications more persistent
    ?></div><?php
}
?>

Ik geef ook de berichten een kleurtje die direct iets vertellen over de status van het bericht (groen voor geslaagd, rood voor fout, oranje voor mogelijk actie nodig).

NB: dit is een van de weinige plekken waar je afwijkt van de regel "filter input escape output" omdat de output in een vorige actie is gegenereerd en de volgende actie niet echt kan inschatten wat er moet gebeuren, daarom is het handiger dat de vorige actie ook gelijk de boodschap formatteert in een formaat dat veilig is voor output.
@Thomas: Dank ik heb de input met check in een formulier. Pas als alles goed staat, kan gesubmit worden. Maar wel graag 1x. Dus ik ga jouw opzet gebruiken. Dank!

Reageren