Hei,
Väsäilen tässäurheiluun liittyvää tulostensyöttö-sivua
Tarkoitus että sivu listaa pelaajat kannasta tauluun ja lomakkeen kenttään voi syöttää tuloksen. tämän jälkeen lisää score-napilla tulokset päivittyisi kantaan.
Koodini toimii osaksi, listaus onnistuu ja tuloksia voi muuttaa ja kun painan lisää score painiketta niin vain taulukon viimeinen score päivittyy.
Miten tämä oikein pitäisi tehdä?
Lomake:
<h3>tulosten muuttaminen</h3> <form action="insert_action2.php" id="form2" title="form2" method="post"> <table id="table1"> <?php $link = mysqli_connect("localhost", "form", "form", "form"); // Check connection if($link === false){ die("ERROR: Could not connect. " . mysqli_connect_error()); } $sql = "SELECT * FROM form2" ; $result = $link->query($sql); while($row = $result->fetch_assoc()){ ?> <tr> <td> <input type="text" name="id" id="id" value="<?php echo $row["id"]; ?>"> <input type="text" name="name" id="name" value="<?php echo $row["name"]; ?>"> </td> <td> <input type="text" name="score" id="score" size="2" value="<?php echo $row["score"]; ?>"> </td> </p> <?php } $link->close(); ?> </tr> </table> <input type="submit" value="Lisää scoret"> </form>
insert_action2.php
<?php $link = mysqli_connect("localhost", "form", "form", "form"); // Check connection if($link === false){ die("ERROR: Could not connect. " . mysqli_connect_error()); } foreach($_POST as $players => $value) { $id = mysqli_real_escape_string($link, $_POST['id']); $name = mysqli_real_escape_string($link, $_POST['name']); $score = mysqli_real_escape_string($link, $_POST['score']); $sql = "UPDATE form2 SET score='$score', name='$name' WHERE id=$id"; if(mysqli_query($link, $sql)){ echo "lines updated to database: <br>$id - $name - $score <br><br><p><p>"; } else{ echo "ERROR: Could not able to execute $sql. " . mysqli_error($link); } } mysqli_close($link); ?>
php-koodi tulostaa nyt tämän:
lines updated to database: 98 - Jouko jormalainen - 150 lines updated to database: 98 - Jouko jormalainen - 150 lines updated to database: 98 - Jouko jormalainen - 150
Mod. korjasi kooditagit: tuloste ei ole PHP-koodia!
Iteroit $_POST-taulukkoa väärin. Voisit aloittaa siitä, että otat selvää, mitä dataa siellä $_POST-taulukossa ylipäätään on. Debuggauksen alkeet.
$_POST-taulukkosi sisältää kolme arvoa: id, name, score. Lomakkeelta ei välity PHP:lle kuin yhden rivin tiedot, koska samannimisiä muuttujia voi olla vain yksi ja siis myöhempi samanniminen kenttä ylikirjoittaa aiemman. Silmukkasi siis kiertää läpi kohdat id, name ja score, ja joka kohdassa tallennat tietokantaan samat arvot. Silmukassa ei ole mitään järkeä, koska et edes yritä käyttää nykyistä arvoa ($players/$value) vaan käytät aina samoja kolmea arvoa. Ohjelmoinnin alkeet hakusessa?
Järkevin tapa usean rivin lähetykseen on käyttää indeksejä kenttien nimissä. Itse pidän selvimpänä, että $_POST-taulukkoon muodostetaan jo lähtökohtaisesti looginen rakenne:
<input type="text" name="data[1][id]" value="1" /> <input type="text" name="data[1][name]" value="Apina" /> <input type="text" name="data[1][score]" value="123" /> <input type="text" name="data[2][id]" value="2" /> <input type="text" name="data[2][name]" value="Banaani" /> <input type="text" name="data[2][score]" value="456" />
Näistä kentistä muodostuu seuraava $_POST-taulukko:
$_POST = [ "data" => [ "1" => ["id" => "1", "name" => "Apina", "score" => "123"], "2" => ["id" => "2", "name" => "Banaani", "score" => "456"], ] ];
Tulokset on helppo käydä läpi silmukalla:
foreach ($_POST["data"] as $vanha_id => $rivi) { $kysely = $pdo->prepare("UPDATE taulu SET id = ?, name = ?, score = ? WHERE id = ?"); $kysely->execute([$rivi["id"], $rivi["name"], $rivi["score"], $vanha_id]); }
Tietokantakyselyssä kannattaisi käyttää valmisteltuja kyselyitä (prepared statement) eikä vanhanaikaista, virhealtista escape-kikkailua. Yllä esitin tämän PDO:lla; en nyt suoralta kädeltä tiedä, miten sama tehtäisiin MySQLi:llä.
Ehdinkin saada homman toimimaan stackoverflow.comista löytämilläni vihjeillä.
Kiitos avusta ja oikein huomasitte että alottelija olen näissä hommissa ja googlen avulla kauhotaan eteenpäin.
Näillä rimpsuilla sain homman toimimaan:
<input type="text" name="score_<?php echo $row["id"]; ?>" id="score_<?php echo $row["id"]; ?>" size="2" value="<?php echo $row["score"]; ?>"> <input type="hidden" name="id[<?php echo $row["id"]; ?>]" id="id[<?php echo $row["id"]; ?>]" value="<?php echo $row["id"]; ?>"> <input type="hidden" name="name_<?php echo $row["id"]; ?>" id="name_<?php echo $row["id"]; ?>" value="<?php echo $row["name"]; ?>">
foreach($_POST['id'] as $pid){ $name = $_POST["name_$pid"]; $score = $_POST["score_$pid"]; $sql = "UPDATE form2 SET score='$score', name='$name' WHERE id=$pid"; if(mysqli_query($link, $sql)){ echo "lines updated to database: <br>$pid - $name - $score <br><br><p><p>"; } else{ echo "ERROR: Could not able to execute $sql. " . mysqli_error($link); } }
Noissa rimpsuissa on vikaa. Hakasulut eivät ole id:ssä sallittuja. SQL-kyselyistä puuttuu nyt kokonaan syötteen käsittely (kuten escape), eli kyselyissä on vakava SQL-injektion mahdollistava tietoturva-aukko. Myös tulosteesta puuttuu käsittelu (kuten htmlspecialchars), joten siinä on myös XSS-tietoturva-aukko. Ylipäänsä ratkaisu on rumempi kuin minun esittämäni, kun kenttien nimissä on kikkailtu osittain taulukoilla ja osoittain alaviivoilla.
Lisäksi jos nyt id:tä ja nimeä ei ole tarpeen muuttaa lomakkeella, kannattaisi poistaa kyseiset kentät kokonaan.
Aihe on jo aika vanha, joten et voi enää vastata siihen.