I dette særtema ser vi på, hvordan cloud og AI bliver fundamentet for virksomhedernes digitale forretning, og hvordan de nye muligheder for automatisering og forretningsværdi kan udnyttes uden at miste overblik, sikkerhed og menneskelig kontrol.
Well, det jeg ville gøre, var at generere en unik ID og smide den i en hidden på selve formularen, når man submitter, vil jeg så gemme denne ID i brugerens sessionvariabel, i et array f.eks., når brugeren så submitter samme formular igen, checker jeg blot om den ID findes i brugerens "submit-array". Hvis den gør, giver vi ham så bare en pæn besked...
Ja, men den kan du jo ikke undgå med mindre du gør som jeg skriver, med javascript ;) Problemet er jo, hvis du svarer ok, så submitter den de samme data igen, og det samme indhold vil blive brugt - Med den sidste strategi, undgår vi dette ;)
Det er jo an på hvad det er for en form, det ligner noget indkøbs noget tilføj indkøbskurven halløj. Hvis nu vedkommende bestiller en trøje og ombestemmer sig og gerne vil bestille en til. Så submitter han formen igen, men du giver ham en pæn besked om han ikke må ;o) Eller misforstod jeg?
Løsningen bliver jeg hopper til forsidenen efter varen er lagt i indkøbskurv, det er til et galleri så der vil altid kun være 1 af hver vare, man kan så klikke på varen i kurven hvis man vil se den igen (den kan ses på forsiden).
Jeg synes POST er en god ting ved vare køb, så kan der ikke fuskes med $_GET i URL'en, og så ser det pææænt ud.
busschou, Han må bare ikke submitte *den samme* form igen, ved hvert side-reload, kan vi lave en ny, unik ID - Faktisk er det måske endda bedst hvis ID'en bliver lavet af et javascript!
<form action="side.php" method="post"> <input type="hidden" name="retpage" value="<?=$_SERVER["PHP_SELF"]?>"> <input type="hidden" name="contxt" value="update"> ... og resten af din form her ... </form>
Filen "side.php":
<? if (isset($_POST["contxt"]) && $_POST["contxt"]=="update") { // Updatater din DB - og hvad du ellers skal header("Location: " + $_POST["retpage"]); } ?>
Det er den metode, der bruges her på Eksperten - og langt de fleste andre steder :)
Hvad er der galt med 'standard' løsningen? Her på E kan man jo bruge 'Back' knappen og/eller reloade en side ligeså meget man lyster, når man har skrvet et indlæg. Det bliver stadig kun indsat én gang - fordi man redirect'er med en header
olebole, hvis jeg når at refreshe min browser inden serveren har sendt mig en location-header (vi snakker teoretisk, hvis nu det er et stort php script, der er flere sekunder om at afvikle) så kan jeg sende data to gange til siden.
Derfor er det ikke en _fuldstændigt_ perfekt løsning - men så absolut den, jeg alligevel altid benytter mig af. Men at kombinere den med en simpel randomstreng, som man smider i session efter submit er ganske enkelt - og så er man helt sikker.
Men der er da ingen grund til at gemme alle de submit-id'er, der er kommet? Man skal da bare gemme det seneste? Jeg kan jo ikke gensubmitte en gammel formular fra meget tidligere (hvis man altså også smider location-headere efter folk, hvilket absolut er det pæneste at gøre rent brugervenlighedsmæssigt).
Jeg skulle lige til at skrive det samme, da jeg reloadede og så barklund havde svaret ;) Det kan sagtens ske at en bruger (mange gør det) trykker to gange, specielt hvis den er et sekund eller to for længe om at loade ;)
Joh, det har du også ret i, jeg er bare vant til at arbejde med scenarier hvor andre siger ting som, "Jamen, hvad nu hvis jeg har to vinduer åbne, og submitter to forskellige formularer?" ;)
Well, for at sige det på en anden måde, når du bruger header(), må der ikke engang blive skrevet et mellemrum ud før - Så dør den med den fejl som du beskriver ;)
barklund >> Hvis man laver en fornuftig struktur, poster man til et specielt dokument, der kun sørger for DB-funktionalitet. Her på stedet hedder det 'response.php' - og er nok dét fornuftige indslag i E's kode ;D
Anyway, så er det så let - og DB-kaldet forhåbentlig så velkonstrueret - at der skal mere end en almindelig spastisk lammelse til at få tingene til at gå i kludder .... men bevares, hvis man absolut *vil* være Toyota-sikker :)
det de prøver sige er : --- <? if (isset($_POST["contxt"]) && $_POST["contxt"]=="update") { // Updatater din DB - og hvad du ellers skal header("Location: " + $_POST["retpage"]); } ?> echo "<html>her kommer alt din html head body osv";
Nøøhhh ... i virkeligheden siger jeg: Hold det i to forskellige dokumenter. I mit forslag indeholder 'side.php' slet ikke HTML - kun PHP.
Ét dokument med 'motoren' ... resten, som ikke har noget med 'motoren' at gøre, i andre dokumenter. Så begynder det at ligne et rigtigt program - og ikke noget en frontend koder har smurt op ;o)
danic >> Ja. God serverkode askiller serversprog og klientsprog skarpt. Det er bare sjældent at se, fordi så ganske få af de, der skriver serverscripts har lært at programmere - men det er afgjort måden at gøre det på.
Derfor bør det heller ikke kunne skabe problemer at anvende headers. Der bør ikke kunne være skrevet HTML ud til browseren, før de sættes - da HTML'en først skrives ud til aller sidst, når al PHP/MySQL er kørt helt færdig :)
olebole, jeg kan kun sige, at jeg er enig. Men det ændrer ikke på den teoretiske mulighed for, at der kan blive lavet rod i databasen. ;)
Men på den anden side, hvis flere submit's direkte kan give rod i databasen, så bør man nok tjekke for disse og håndtere dem korrek - for ellers skal der nok komme en eller anden irriterende script-kiddie forbi, der kun er ude på ballade :)
barklund >> Det er vist kun små bitte nuancer, vi kan få en diskusion om her ;o) Det virker helt klart også på mig, somom det er den grundlæggende struktur, den er gal med her :)
olebole> top.php indeholder html kode + nogle php includes som indeholder indkøbskurv og en dynamisk php menu, hvad skal jeg gøre for at rette op på det?
<form action="side.php" method="post"> <input type="hidden" name="retpage" value="<?=$_SERVER["PHP_SELF"]?>"> <input type="hidden" name="contxt" value="update"> ... og resten af din form her ... </form>
Filen "side.php":
<? if (isset($_POST["contxt"]) && $_POST["contxt"]=="update") { // Updatater din DB - og hvad du ellers skal header("Location: " + $_POST["retpage"]); } ?>
Filen 'side.php' indeholder alle dine indsæt-, ret-, slet-, osv-funktioner - men intet HTML. Når du skal indsætte noget i DB'en, poster du formen mod dette dokument, der foretager, hvad der skal fortages - og sender brugeren tilbage til siden med formen (eller en anden, hvis det ønskes).
På den måde har du fuldstændig styr og overblik over dit program ... i stedet for, det ligger spredt ud over dusinvis af forskellige dokumenter med program og interface rodet sammen i én pærevælling.
Det første kan komme til at ligne programmering. Det sidste kan højst komme til at ligne lidt hygge-skribleri i et scriptsprog :)
Jeg er fuldstændig enig med at koden bør ligger som øverst i en funktions-fil, hvis jeg antager at "side.php" er en funktions fil som indeholde en update funktion,
function update() { if (isset($_POST["contxt"]) && $_POST["contxt"]=="update") { // Updatater din DB - og hvad du ellers skal header("Location: " + $_POST["retpage"]); } } // end func
Så bliver jeg nød til at kalde update funktionen fra min html-kode (bruger interfacet) <?PHP update(); ?> Men når funktionen køres vil det så ikke give et problem med header?
Nej, du inkluderer den ikke i noget. Du har to filer, der ikke har eller får noget med hinanden at gøre. Én fil med formen og én med funktionen, der sætter ind i DB. Når du subitter formen, gør du det mod filen med funktionen. Her opdateres DB'en og brugeren redirecte's til siden med formen.
Det er måden, jeg selv holder mine DB-funktioner i en fil for sig selv. Det giver et godt overblik ... for mig. Der er andre, der inkluderer deres funktioner i toppen af inteface-filen. Det er meget en smagssag, hvis man i øvrigt holder orden i koden :)
Når du har PHP og HTML i samme fil - og det vil du altid have, uanset hvilken hovedmodel du vælger - er det vigtigt stadig at holde det adskilt. Undlad at skrive HTML ud midt i din PHP. Skriv hellere f.eks:
<? $result = [EN_MYSQL_FORESPØRGSEL]; $s = ""; while ($row=mysql_fetch_assoc($result)) { $s += "<tr><td>".$row["navn"]."</td><td>".$row["email"]."</td></tr>"; } // - og en bunke andet PHP, der gør en masse andet ?> <html> <body>
<table> <?=$s?> </table
</body> </html>
- tag dig ikke af den alt for forsimplede HTML-kode ... det er kun et eksempel. Det vigtige at hive ud af eksemplet, er:
*** Skriv aldrig HTML ud i din PHP. Skriv i stedet til 'streng-buffere', som skrives ud nede i HTML'en ***
På den måde bliver din kode overskuelig - og du kan bruge sessions, cookies og headers uden problemer med 'for tidlig HTML-afgang' ;o)
En behagelig bivirkning er, at det er langt hurtigere at skrive kode ud på den måde. Skal PHP hele tiden hoppe ud og ind i 'skrivemaskinen' i løkker, tager det en krig at skrive en tabel i forhold til, hvis du skriver til en buffer. Det er ikke sikkert, du mærker det ved et enkelt dokument - men det betyder meget for serveren ved mange sidekald ... og man bør vel altid have som udgangspunkt, at man er ved at skrive en populær side, som mange vil læse :)
Med en streng-buffer mener jeg en streng, man skiver til - i stedet for at skrive ud 'på stedet'. F.eks. variablen $s her:
$s = ""; while ($row=mysql_fetch_assoc($result)) { $s += "<tr><td>".$row["navn"]."</td><td>".$row["email"]."</td></tr>"; }
Du bruger variablen $s som en 'buffer', der fyldes med HTML-kode - og venter med at skrive den ud, til du når det ønskede sted nede i HTML-delen af dokumentet:
<table> <?=$s?> </table>
Den rigtig dårlige - og skræmmende udbredte - måde at gøre det på, er:
<table> <? while ($row=mysql_fetch_assoc($result)) { echo "<tr><td>".$row["navn"]."</td><td>".$row["email"]."</td></tr>"; } ?> </table>
Det giver en rodet kode og det performer voldsomt meget dårligere. Tager en side ét sekund at generere med første metode, kan det meget vel tage 2-300 sekunder med den sidste! Det er helt urealistiske genereringstider, men det viser forholdet :)
Der er flere måder at opnå det samme på. Én metode er, som jeg viste i mit forrige indlæg ... en anden og bedre er at pakke koden ind i en funktion, der returnerer HTML-strengen:
<? function writeTableCont() { $result = [EN_MYSQL_FORESPØRGSEL]; $s = ""; while ($row=mysql_fetch_assoc($result)) { $s += "<tr><td>".$row["navn"]."</td><td>".$row["email"]."</td></tr>"; } return $s; }
// - og en bunke andet PHP, der gør en masse andet ?> <html> <body>
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.