Avatar billede lsskaarup Nybegynder
06. august 2010 - 11:41 Der er 15 kommentarer og
1 løsning

Dynamisk opbygning af MySQL query ud fra en foreach

Jeg har lidt problemer med at knækket en nød...

Jeg har en side, der indeholder et dynamisk antal text-felter. Antallet af felter er dynamisk fordi de bekriver antallet at etaper vedr. en sag, men de er ens for hver etape. Jeg har derfor navngivet dem så deres navn indeholder etapeid'et for at kunne adskille dem f.eks. "feltnavn_id".

Når der submittes på siden, skal de fanges af en anden side, som skriver dem i en MySQL db.

Jeg fanger dem vha. en foreach og trækker deres værdierne ud i den, men jeg kan ikke lige se, hvordan jeg skal håndtere etapeid'et, så jeg får opdateret de rigtige felter.

Koden:
$antal_etaper = $_POST['antalEtaper'];
    $ordreid = $_POST['eid'];
    $thispage = $_POST['thispage'];
    unset($_POST['antalEtaper']);
    unset($_POST['eid']);
    unset($_POST['thispage']);

    $keys = array_keys($_POST);

    $query = array();//til forespørgelerne
               
    foreach ($keys as $nøgle => $feltnavn) {
        $værdi = $_POST[$feltnavn];

        $query[] = '`'.$feltnavn.'` = \''.addslashes($værdi).'\'';
    }

    echo $tmp = 'UPDATE `etape` SET '.implode(', ', $query).' WHERE id = '????' AND ordreid='.$ordreid.' or die(mysql_error())';

Problemet er at queryen kommer til at indeholder alle felter for alle etaper, men jeg skal have dem opsplittet hver etape for sig.
Avatar billede showsource Seniormester
06. august 2010 - 11:52 #1
Jeg ville bruge [] i feltnavn.
name="etape_id[]" value="<?php echo $id; ?>"

Nu er det vel "tænkt" kode du viser ?
Jeg ville aldrig bruge specieltegn til php navne
Avatar billede lsskaarup Nybegynder
06. august 2010 - 12:59 #2
Kan jeg så gribe den på samme måde, hvis [] kommer i feltnavnet?

Hvad mener du lige med specialtegn i php?
Avatar billede lsskaarup Nybegynder
06. august 2010 - 13:30 #3
Ahh, nu kan jeg se, hvor du vil hen, men hvordan får jeg den til at steppe igennem felternes værdier, hvis jeg har f.eks. 3 felt[]?

Lige nu returnerer den første værdi hele tiden.

$ordreid = $_POST['eid'];
$thispage = $_POST['thispage'];
$etape = array();
$etape = $_POST['etapeid'];
//echo $_POST['e1'][0];
unset($_POST['antalEtaper']);
unset($_POST['eid']);
unset($_POST['thispage']);
unset($_POST['etapeid']);

$keys = array_keys($_POST);
$etapeid;
//print_r($keys);

$query = array();//til forespørgelerne
   
for ($j=0; $j<count($etape); $j++) {
    $etapeid = $etape[$j];
    foreach ($keys as $nøgle => $feltnavn) {
        //echo $_POST[$feltnavn];
        for ($i=0; $i<count($_POST[$feltnavn]); $i++) {
            $værdi = $_POST[$feltnavn][$i];
            $query[] = '`'.$feltnavn.'` = \''.addslashes($værdi).'\'';
        }
    }
    echo $tmp = 'UPDATE `etape` SET '.implode(', ', $query).' WHERE id = '.$etapeid.'  AND ordreid='.$ordreid.' or die(mysql_error())';
    echo "<br>";
    echo "<br>";
}
Avatar billede lsskaarup Nybegynder
06. august 2010 - 13:56 #4
Hov opdagede at jeg havde en forlække for meget, men det har ikke rigtigt hjulpet på at kunne fange de rigtige variabler.

$ordreid = $_POST['eid'];
$thispage = $_POST['thispage'];
$etape = array();
$etape = $_POST['etapeid'];
//echo $_POST['e1'][2];
unset($_POST['antalEtaper']);
unset($_POST['eid']);
unset($_POST['thispage']);
unset($_POST['etapeid']);

$keys = array_keys($_POST);
$etapeid;
//print_r($keys);

$query = array();//til forespørgelerne
               
for ($j=0; $j<count($etape); $j++) {
    $etapeid = $etape[$j];
    foreach ($keys as $nøgle => $feltnavn) {
        //echo $_POST[$feltnavn];
        //for ($i=0; $i<count($_POST[$feltnavn]); $i++) {
        $værdi = $_POST[$feltnavn][$j];
        $query[] = '`'.$feltnavn.'` = \''.addslashes($værdi).'\'';
    }

    echo $tmp = 'UPDATE `etape` SET '.implode(', ', $query).' WHERE id = '.$etapeid.'  AND ordreid='.$ordreid.' or die(mysql_error())';
}

Hvis jeg udskriver $værdi = $_POST[$feltnavn][$j]; får jeg de rigtige værdier, men de kommer med med i selve query'en...
Avatar billede showsource Seniormester
06. august 2010 - 14:25 #5
hmm, du vil ha' "ukendt feltnavn" opdateret ?
Altså, du ved IKKE hvilke felter fra tabel der bliver vist ?

Med specialtegn mener jeg æ,ø,å m.m.
Avatar billede showsource Seniormester
06. august 2010 - 14:38 #6
Hmm, her er et ex. hvor du kender feltnavne:

<html><head></head>

<body>

<form action="" method="post">


<?php
for($i = 1; $i < 5; $i++) {


echo'
<p>

Etape '.$i.'
<br />
<input type="hidden" name="etapeid[]" value="'.$i.'">

<input type="text" name="feltnavn_et[]" value="value for feltnavn_et og id '.$i.'">
<br />
<input type="text" name="feltnavn_to[]" value="value for feltnavn_to og id '.$i.'">
<br />
<input type="text" name="feltnavn_tre[]" value="value for feltnavn_tre og id '.$i.'">

';
}

?>

<p>
<input type="submit" value="Lav query">
</form>

<?php

if(isset($_POST["etapeid"]) && is_array($_POST["etapeid"])) {

$antal = count($_POST["etapeid"]);

    for($a = 0; $a < $antal; $a++) {

    $sql = "UPDATE tabel SET ";

    $sql .= "feltnavn_et = '".$_POST["feltnavn_et"][$a]."', feltnavn_to = '".$_POST["feltnavn_to"][$a]."', feltnavn_tre = '".$_POST["feltnavn_tre"][$a]."' WHERE id = ".$_POST["etapeid"][$a];

    echo $sql."<br>";

    }

}


?>

</body></html>

I stedet for echo $sql skal der jo så køres en mysql_query()
Avatar billede lsskaarup Nybegynder
06. august 2010 - 14:42 #7
Tja, det kommer an på hvad du mener med "ukendt". Jeg kender jo alle felterne, men så alligevel ikke, da de laves dynamisk ud fra hvor mange etaper der er.

Det er lidt svært at forklare, men jeg ligger lige et billede op, som viser indtastningssiden.

http://www.billedeupload.dk/photo/2010-08/29ae1641/etape.JPG.html (tallene 1, 5 og 3 udgør id'erne i db'en)

* Der er 3 rækker, hver række udgør en etape.
* De bliver dynamisk oprettet vha. en forløkke, idet jeg kigger i db'en, for at se hvor mange etaper der er. Derfor døber jeg felterne som du forslog med feltnavn[].
* Når siden gemmes, skal felterne opdateres i db'en.

Det vil sige, at jeg skal have en UPDATE-query til hver etape-id.

Håber det hjalp lidt på forståelsen.
Avatar billede intenz Novice
06. august 2010 - 15:29 #8
Nu har jeg ikke sat mig ind i alt hvad i har skrevet. Men du kan lave navnene på felterne som et array (som skrevet tidligere), men du kan også inddele det yderligere.

Et test eksempel (tilfældige variabel navne):
// 'etape 1'
<input type="text" name="etaper[etape_1][id]" value="1">
<input type="text" name="etaper[etape_1][navn]" value="etape 1">
<input type="text" name="etaper[etape_1][ordreid]" value="424">

// 'etape 2'
<input type="text" name="etaper[etape_2][id]" value="5">
<input type="text" name="etaper[etape_2][navn]" value="etape 2">
<input type="text" name="etaper[etape_2][ordreid]" value="121">

Og så i PHP hente dem ud med:

<?php
foreach ($_POST['etaper'] as $data) {
  $query = array();
  foreach ($data as $key => $value) {
    if ($key == 'id') {
      $query['etapeid'] = $value;
    } else if ($key == 'ordreid') {
      $query['ordreid'] = $value;
    } else {
      $query['data'][] = '`'.$key.'` = \''.addslashes($value).'\'';
    }
  }
  $sql = 'UPDATE `etape` SET '.implode(', ', $query['data']).' WHERE id = '.$query['etapeid'].'  AND ordreid='.$query['ordreid'];
  print $sql."<br><br>";
  // mysql_query($sql) or die( mysql_error() )

}
?>
Avatar billede intenz Novice
06. august 2010 - 15:37 #9
Og istedet for at lave unset på POST variabler du ikke skal bruge, så lav et array med dem du skal bruge, og tjek dem deri. Det gør det mere fleksibelt (og så glemmer du ikke at unsette noget hvis du ændrer i det)

$allowedKeys = array('name', 'noget_andet', 'noget_tredje');

Det kan du så tjekke i loopet med:

  ...
  $query['ordreid'] = $value;
    } else {
      if (in_array($key, $allowedKeys)) {
        $query['data'][] = '`'.$key.'` = \''.addslashes($value).'\'';
      }
    }
  }
  ...

Hvis den så ikke er tilladt, bliver den bare sprunget over.
Avatar billede lsskaarup Nybegynder
06. august 2010 - 17:44 #10
intenz -> Jeg skal lige kigge nærmere på det første du har skrevet. Men det sidste vil jeg ikke mene er praktisk muligt. Det drejer sig måske om 3-4 felter, som ikke skal med, men i teorien uendeligt mange som skal med, så der har jeg valgt det mindste af 2 onder.

Det kan måske gøres smartere på en eller anden måde, men nu skal jeg bare i første omgang have funktionaliteten til at virke.
Avatar billede intenz Novice
06. august 2010 - 17:52 #11
-> #10
Okay, så ville jeg heller ikke gøre det på den måde jeg beskrev :)
Avatar billede showsource Seniormester
06. august 2010 - 23:09 #12
hmm, hvis du nu henter feltnavne ved hver request, hvad enten det er GET eller POST:

$mycols = array();
$cols = mysql_query("SHOW COLUMNS FROM dintabel") or die (mysql_error());

while($col = mysql_fetch_object($cols)) {
$mycols[] = $col->Field;
}

mysql_free_result($cols);

så har du et array bestående af de felter som skal opdateres.
Du kan også bruge LIKE til kun at hente bestemte felter, hvis du f.eks. navngiver dem "ensartet",
etapeid, etapekm, etapestart, etapested etc.

$cols = mysql_query("SHOW COLUMNS FROM dintabel LIKE 'etape%'") or die (mysql_error());

Nås du ved visning af formfelter igen bruger det hiddenfelt med id

name="etapeid[]" value="<?php echo $id; ?>"

og felterne i arrayet bruger:

name="etape_km[<?php echo $id; ?>]" value="feltvalue"

kan du ved post:

$antal = count($_POST["etapeid"]);
$colsantal = count($mycols);

for($i = 0; $i < $antal; $i++) {

$colsql = array();

    for($c = 0; $c < $colsantal); $c++) {
    $colsql[] = $mycols[$c]." = '".$_POST[$mycols[$c][$i]."'";
    }
$sql = "UPDATE tabel SET ".implode("," $colsql)." WHERE id = ".$_POST["etapeid"][$i];

}


utestet, men gi'r vel lidt mening ?
Avatar billede lsskaarup Nybegynder
09. august 2010 - 13:13 #13
Intenz -> Jeg kan ikke rigtigt se, hvordan din løsning afhjælper problemet med at f.eks. etape[2] bliver gemt ved etape 1's id...
Avatar billede lsskaarup Nybegynder
09. august 2010 - 15:18 #14
Hov, nu tror jeg snart den er der, har i hvert fald fået opsplittet så hver etape har sin egen update. Løsningen var sådan set meget simpel, men det er svært at se skoven for bare træen engang imellem... :-)

Men jeg er ikke helt sikker på den endnu, for jeg har nogle checkbox, som ikke bliver fanget af $_POST[]. Kan de ikke det, eller sagt på en anden måde, hvordan fanger jeg dem lige så?
Avatar billede lsskaarup Nybegynder
09. august 2010 - 16:32 #15
Aha, checkboxe eksisterer åbenbart ikke så længe de ikke er udfyldt, for vinger jeg én af, bliver den godt nok gemt. Jeg kan bare ikke fjerne checket igen, men det må jeg lige rode videre på et andet tidspunkt.

Løsningen som jeg fik til at virke ser sådanne nu. Der er også kode til automatisk at oprette felterne i databasen.

$ordreid = $_POST['eid'];
$thispage = $_POST['thispage'];
$etape = array();
$etape = $_POST['etapeid'];
unset($_POST['antalEtaper']);
unset($_POST['eid']);
unset($_POST['thispage']);
unset($_POST['etapeid']);

//Vi skal have oprettet eventuelle nye felter automatisk i databasen
$keys = array_keys($_POST);
$keygroup = array();
$keygroup[0] = array();  // Field 1-99
for ($i=0; $i<count($keys); $i++) {
    if (eregi("([E]?)([0-9]{1,3})([A-Z]?)", $keys[$i], $regs)) {
        $index = sprintf('%03d', $regs[2]);
        $keygroup[substr($index,0,1)][] = $keys[$i];
    } else {
        $keygroup[0][] = $keys[$i];
    }
}

for ($i=0; $i<=1; $i++) {
    if (sizeof($keygroup[$i])) {
        // Check for existing fields
        $dbfields = mysql_query('SHOW COLUMNS FROM `etape`');
        $dbcols = mysql_num_rows($dbfields);
       
        $dbc = array();
        for ($j=0; $j<$dbcols; $j++) {
            $row = mysql_fetch_assoc($dbfields);
            $dbc[$j] = $row['Field'];
        }

        for ($j=0; $j<count($keygroup[$i]); $j++) {
            if (!in_array($keygroup[$i][$j], $dbc)) {
                $opret = 'ALTER TABLE `etape` ADD `'.$keygroup[$i][$j].'` TINYTEXT';
                mysql_query($opret) or die('Fix table '.mysql_error());
            }
        }
    }
}

   
//Indsætter nu data i alle felter
$querys = array();//til forespørgelerne
               
for ($j=0; $j<count($etape); $j++) {
    foreach ($keys as $feltnavn) {
        $værdi = $_POST[$feltnavn][$j];
        $querys[] = "`".$feltnavn."` = \"".addslashes($værdi)."\"";
    }
    $tmp = 'UPDATE `etape` SET '.implode(', ', $querys).' WHERE id = '.$etape[$j].'  AND ordre_id = '.$ordreid;       
    unset($querys);//Sletter $query så den ikke bliver længere og længere for hver omgang i løkken
    mysql_query($tmp) or die(mysql_error());
}
header('Location: /popupentreordre/ordre'.$nextpage.'/'.$ordreid.'/');

Showsource -> Smid et svar, du hjalp mig langt hen af vejen.
Avatar billede showsource Seniormester
10. august 2010 - 13:18 #16
et svar
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