Avatar billede danic Nybegynder
13. maj 2005 - 20:32 Der er 50 kommentarer og
1 løsning

submit af form ved reload?

Jeg har en simpel form:

                <FORM name="buy" method="post" action="?attach=showproduct&productid=<?=$_GET[productid]?>">
                <input type="hidden" name="addbasket" value="<?=$_GET[productid]?>">
                <input type="hidden" name="productid" value="<?=$_GET[productid]?>">
                <input type="hidden" name="currentprice" value="<?=$currentprice?>">
                <input type="hidden" name="shortname" value="<?=$shortname?>">
                <input name="submit" type="image" src="vareinfo_bestil.gif" width="107" height="61"">
                </FORM>

problemet er at hvis jeg klikker submit og der efter reload af siden så kører den 2 gange, den må kun kører en gang - og der er ved klik på submit ???
Avatar billede busschou Praktikant
13. maj 2005 - 20:33 #1
lytter lige med hvis en har en løsning
Men jeg tror ikke der findes en løsning. For variablene postes jo...
Avatar billede coderdk Praktikant
13. maj 2005 - 20:36 #2
På siden som du submitter til, kan du f.eks. lave denne i bunden:

<script type="text/javascritp" language="javascript">
  window.location.replace( 'andenside.php' );
</script>

Du kunne også nøjes med at bruge header( 'location: andenside.php' ); men så kan du vist bruge back-knappen ;P
Avatar billede busschou Praktikant
13. maj 2005 - 20:37 #3
coderdk >> Men hvis man klikker tilbage i browseren... så vil de vel stadig postes ;o)
Avatar billede danic Nybegynder
13. maj 2005 - 20:44 #4
jeg er ikke til javascrip fusk :-) det kunne dog være godt hvis man kunne nul-stille en post variabel. Alternativt på jeg action="index.php"
Avatar billede coderdk Praktikant
13. maj 2005 - 20:47 #5
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...
Avatar billede busschou Praktikant
13. maj 2005 - 20:49 #6
Hehe men den besked får man jo i forvejen som regel noget i retningen af "siden du opfrisker indeholder post variable, ønsker du fortsætte?" :o)
Avatar billede coderdk Praktikant
13. maj 2005 - 20:52 #7
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 ;)
Avatar billede busschou Praktikant
13. maj 2005 - 20:58 #8
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?
Avatar billede ksoren Nybegynder
13. maj 2005 - 20:59 #9
Det er vel blot et spørgsmål om at kigge på submit type, og omdirigere..

<?php
if($_SERVER['REQUEST_METHOD'] == "POST"){
    // submitted
    $query = $_SERVER['QUERY_STRING'];
    header("Location: ?$query");
    exit();
}
?>
<FORM name="buy" method="post" action="?attach=showproduct&productid=<?=$_GET['productid']?>">
...
Avatar billede danic Nybegynder
13. maj 2005 - 21:02 #10
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.
Avatar billede busschou Praktikant
13. maj 2005 - 21:04 #11
Hvis du vil sikre dig bedre mod fusk ville jeg foreslå dig helt droppe get og post og udelukkende benytte sessions
Avatar billede danic Nybegynder
13. maj 2005 - 21:11 #12
det kører i sessions, men "Køb "knappen skal jo aktivere købet før den ligges i session
Avatar billede coderdk Praktikant
13. maj 2005 - 21:25 #13
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!

<script type="text/javascript">
function doId()
{
  document.getElementById('checksum').value = Math.random();
}
</script>
<form method="post" action="script.php" onsubmit="return doId()">
<input type="hidden" name="checksum" id="checksum" value="0" />
flere felter...
</form>

Så vil den lave en ny ID hver gang man trykker på submit ;)
Avatar billede olebole Juniormester
13. maj 2005 - 21:26 #14
<ole>

<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  :)

/mvh
</bole>
Avatar billede coderdk Praktikant
13. maj 2005 - 21:27 #15
Og hov, funktionen:

function doId()
{
  document.getElementById('checksum').value = Math.random();
}

Skulle være:

function doId()
{
  document.getElementById('checksum').value = Math.random();
  return true;
}
Avatar billede danic Nybegynder
13. maj 2005 - 21:29 #16
coderdk> så skal jeg vel kender den første id ?

if ($_POST[checksum] =="unikid"){
smider varen i sessions
}
Avatar billede olebole Juniormester
13. maj 2005 - 21:31 #17
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
Avatar billede coderdk Praktikant
13. maj 2005 - 21:33 #18
Noget i stil med:

if ( is_array( $_SESSION['submitarray'] ) && in_array( $_POST['checksum'], $_SESSION['submitarray'] ) )
{
  // brugeren har allerede submittet denne formular
}
else
{
  if ( !is_array( $_SESSION['submitarray'] ) )
  {
      $_SESSION['submitarray'] = array();
  }
  $_SESSION['submitarray'][] = $_POST['checksum'];
  // smid varer i sessions
}
Avatar billede olebole Juniormester
13. maj 2005 - 21:35 #19
Tjahh ... hvis man insisterer på bøvlede løsninger, sååå ....  :)
Avatar billede barklund Nybegynder
13. maj 2005 - 21:41 #20
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.
Avatar billede barklund Nybegynder
13. maj 2005 - 21:42 #21
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).
Avatar billede coderdk Praktikant
13. maj 2005 - 21:44 #22
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 ;)
Avatar billede danic Nybegynder
13. maj 2005 - 21:44 #23
olebole> Problemet med header er: Cannot modify header information - headers
Avatar billede coderdk Praktikant
13. maj 2005 - 21:45 #24
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?" ;)
Avatar billede coderdk Praktikant
13. maj 2005 - 21:46 #25
danic, Jamen, det er jo fordi du har skrevet noget ud tidligere på siden, det må du ikke når du bruger header()
Avatar billede coderdk Praktikant
13. maj 2005 - 21:47 #26
Alternativt kunne man måske bare disable submitknappen når man har trykket på den ;)
Avatar billede barklund Nybegynder
13. maj 2005 - 21:49 #27
danic, det er ikke et problem med header, det er et problem med dit script!
Avatar billede danic Nybegynder
13. maj 2005 - 21:49 #28
coderdk> tja ikke så tosset en ide og så lige opdater varen i mysql - som pending, så der ikke er andre der køber den, det er jo unikke varer.
Avatar billede danic Nybegynder
13. maj 2005 - 21:52 #29
Jeg har ikke noget andet javascrip liggende:

http://www.gallerioscar.dk/
Avatar billede coderdk Praktikant
13. maj 2005 - 21:59 #30
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 ;)
Avatar billede danic Nybegynder
13. maj 2005 - 22:02 #31
skal den så ligge <header>her</header> ?
Avatar billede barklund Nybegynder
13. maj 2005 - 22:05 #32
Nej, en header er _ikke_ HTML- det er HTTP. Den skal slet ikke outputtes/printes og intet andet må være outputtet/printet før den.

Kig i manualen under header :)

--
Morten Barklund
Avatar billede olebole Juniormester
13. maj 2005 - 22:08 #33
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  :)
Avatar billede busschou Praktikant
13. maj 2005 - 22:09 #34
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";
Avatar billede danic Nybegynder
13. maj 2005 - 22:12 #35
Er det normalt at have en "masse" kode liggende før "html koden", når det er en dynamisk side skal det jo loades hvergang?
Avatar billede olebole Juniormester
13. maj 2005 - 22:12 #36
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)
Avatar billede danic Nybegynder
13. maj 2005 - 22:16 #37
Jeg har en motor, men den er måske forkert opbygget?

require("connect.php");
$db = opendb();
       
    include("top.php");
    if ($_GET["attach"] == NULL)
    {
        $_GET["attach"] = "show";
        $_GET["menuid"] = 10000;   
    }
   
    if ($_GET["attach"] != NULL){           
        if (isset($_GET["directory"])) {
            include("language/danish/".$_GET["directory"].".php");
            $attach_file = $_GET["directory"] . "/" . $_GET["attach"] . ".php";
        } else {
            $attach_file = $_GET["attach"] . ".php";
        }           
        if (file_exists($attach_file)) {
            include($attach_file);
        } else {
            include('fejl.php');
        }
    } 

    include("bottom.php");
    exit;
Avatar billede olebole Juniormester
13. maj 2005 - 22:16 #38
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  :)
Avatar billede barklund Nybegynder
13. maj 2005 - 22:17 #39
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 :)

--
Morten Barklund
Avatar billede olebole Juniormester
13. maj 2005 - 22:18 #40
danic >> Ja, hvis 'top.php' indeholder HTML-kode - eller PHP, der udskriver HTML, er det ikke en hensigtsmæssig opbygning
Avatar billede olebole Juniormester
13. maj 2005 - 22:20 #41
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  :)
Avatar billede danic Nybegynder
13. maj 2005 - 22:23 #42
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?
Avatar billede danic Nybegynder
13. maj 2005 - 22:46 #43
Eller mener du at jeg skal kode en PHP motor som Parser .html sider for dynamiske tags sådan her f.eks.

<td colspan="3" class="tabkop">
[LABEL]
[?ALINK[ID]?]
- <a class="LinkA" href='[LINK]' target="_new">View</a>
[?/ALINK[ID]?]
</td>
?
Avatar billede olebole Juniormester
13. maj 2005 - 23:26 #44
Her er motoren skilt fra interface'et:

<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  :)
Avatar billede danic Nybegynder
14. maj 2005 - 09:05 #45
olebole>

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?
Avatar billede olebole Juniormester
14. maj 2005 - 16:03 #46
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  :)
Avatar billede danic Nybegynder
14. maj 2005 - 16:24 #47
Tak for alle de afledte svar, olebole>

jeg formoder at 'streng-buffere' = $_SERVER[var]
"skriver til en buffer" = $_SESSION[var]

Du må gerne smide et svar :-)
Avatar billede olebole Juniormester
14. maj 2005 - 19:11 #48
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>

<table>
<?=writeTableCont()?>
</table

</body>
</html>
Avatar billede olebole Juniormester
14. maj 2005 - 19:19 #49
Nåja ... og et svar. For det ikke skal være løgn, ser man faktisk også af og til løsninger à la det her:

<table>
<?
while ($row=mysql_fetch_assoc($result)) {
?>
    <tr><td><?=$row["navn"]?></td><td><?=$row["email"]?></td></tr>
<?
}
?>
</table>

- så *kan* PHP-kode ikke blive mere syg!  :)
Avatar billede danic Nybegynder
15. maj 2005 - 23:25 #50
Tak for hjælpen og alle de gode svar!
Avatar billede olebole Juniormester
16. maj 2005 - 00:43 #51
- selvtak ... og for points  :)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester