Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: PHP ja MySQL: Usean rivin UPDATE

Othnos [17.05.2010 23:07:01]

#

Tervehdys Ohjelmointiputkalaiset.

Tarvitsen neuvoja hyvään toteutus tapaan päivittäessä useaa riviä yhdellä formilla tietokantaan.

Tein esimerkin, josta saatte käsityksen mitä olen hakemassa.

Esimerkki tarvitsee tietokannan db, taulun maat, jossa sarakkeet id, nimi, kansalaisuus sekä muutaman rivin tietoja.

<?php
//Yhdistetään tietokantaan
$yhteys = mysql_connect("localhost" , "username", "password");
if(!$yhteys)
{
	die('Could not connect: ' . mysql_error());
}

//Valitaan tietokanta
$tietokanta = mysql_select_db("db", $yhteys);
if(!$tietokanta)
{
	die(mysql_error());
}

//Valitaan PHP:n merkistö
mysql_set_charset('utf8',$yhteys);

//Uusien tietojen tallennus tietokantaan
if(isset($_POST['submit']))
{
	//Haetaan lähetetyt tiedot array-muuttujiin
	$id = array();
	$nimi = array();
	$kansalaisuus = array();

	$id = $_POST['id'];
	$nimi = $_POST['nimi'];
	$kansalaisuus = $_POST['kansalaisuus'];

	for($i = 0; $i < count($id); $i++)
	{
		$sql = "UPDATE maat SET nimi = '".mysql_real_escape_string($nimi[$id[$i]])."', kansalaisuus = '".mysql_real_escape_string($kansalaisuus[$id[$i]])."' WHERE id = '".$id[$i]."'";
		$result = mysql_query($sql) or trigger_error(mysql_error(), E_USER_ERROR);
	}
}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns = "http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" />
<title></title>
</head>

<body>
<form method = "post" action = "<?php echo $_SERVER['PHP_SELF']?>">
<table>
<tr>
	<th>Maan nimi:</th>
	<th>Kansalaisuus:</th>
</tr>
<?php

//Haetaan maiden nimet tietokannasta
$sql = "SELECT * FROM maat";
$result = mysql_query($sql) or trigger_error(mysql_error, E_USER_ERROR);

//Jos haku onnistui tulostetaan input-kentät
if($result)
{
	for($i = 0; $info = mysql_fetch_row($result); $i++)
	{
		echo '<tr><td>';
		echo '<input type = "hidden" name = "id['.$i.']" value = "'.$info[0].'" />';
		echo '<input type = "text" name = "nimi['.$info[0].']" value = "'.htmlspecialchars($info[1]).'" />';
		echo '</td>';
		echo '<td>';
		echo '<input type = "text" name = "kansalaisuus['.$info[0].']" value = "'.htmlspecialchars($info[2]).'" />';
		echo '</td></tr>'."\n";
	}
}

?>
<tr>
	<td><input type = "submit" name = "submit" value = "Tallenna" /></td>
</tr>
</table>
</form>
</body>

</html>

Tulisiko minun hakea vanhat tiedot tietokannasta ja verrata if-lauseella uusiin ja vain tietojen vaihtuessa tallentaa tiedot tietokantaan?

Antti Laaksonen [17.05.2010 23:35:03]

#

Yksi ratkaisu on käyttää piilokenttiä, jotka sisältävät rivien vanhat tiedot. Riviä täytyy päivittää vain, jos piilokentät eroavat tekstikentistä.

Toisaalta nykyinen toteutuksesikin lienee käytännössä riittävä.

Metabolix [17.05.2010 23:41:08]

#

Kikkailet turhaan for-silmukalla ja piilotetuilla id-kentillä. Voisit tehdä suoraan näin:

<?php
foreach ($_POST['nimi'] as $id => $nimi) {
  $kansalaisuus = $_POST['kansalaisuus'][$id];
  // Nyt on kätevästi muuttujat $nimi, $kansalaisuus, $id.
}

Koodissasi on SQL-injektion paikka, koska et tarkista id-syötettä mitenkään. Voisit varmuuden vuoksi muuttaa sen kokonaisluvuksi ((int)$id).

HTML:ssä =-merkin ympärille ei kuulu välejä.

tsuriga [17.05.2010 23:52:48]

#

Ja PHP_SELF on turvaton (vieläkö/-kin?), käytä sen tilalla SCRIPT_NAMEa.

Othnos [18.05.2010 00:01:45]

#

Kiitos todella hyvistä ajatuksista, joilla voin korjata koodinkirjoitustani entistä paremmaksi. Taidan lukea vielä PHP-oppaan uudelleen lävitse, koska kyseinen foreach-funktio on jäänyt minulta kokonaan käyttämättä ja nopeasti vilkaistuna todellakin helpottaa ainakin tässä tilanteessa.

"Piilokentät" olisi koodin optimoinnin kannalta varmaan parempi ratkaisu, kuin nykyinen, jos ajatellaan, että rivejä olisi yli 20 ja sarakkeita noin sama määrä. Ei taida tosin nykytekniikalla tuottaa hirveitä eroja, mutta en tiedä miten laajoja projekteja joudun tulevaisuudessa käsittelemään.

Jos joku vielä edellä mainittujen tapojen lisäksi keksii jotain rakentavaa palautetta ottaisin sen mielihyvin vastaan.

Othnos [23.05.2010 16:50:21]

#

Kyseistä aihetta sivuten olisi vielä yksi javascript-ongelma.

Olen tulostanut jokaiselle riville samaa metodia käyttäen checkbox-kentät joiden avulla on tarkoitus määrittää mitkä rivit tallennetaan yms. Ongelmani on saada "check/uncheck all checkboxes" ominaisuus toimimaan.

Sain koodattua seuraavan esimerkin, mutta se toimii vain jos jokaisella checkboxilla on sama nimi, joka tässä tapauksessa ei ole mahdollista.

<html>

<head>
<script type="text/javascript">
function selection()
{
	//Noudetaan valitse_kaikki-checkboxin arvo muuttujaan
	valitse_kaikki = document.getElementById('valitse_kaikki');
	//Jos checkbox valittu valitaan kaikki valinta-checkboxit
	if(valitse_kaikki.checked == true)
	{
		//Ongelman ydin. Kuinka saada esimerkiksi hakemaan divin perusteella tai että hakee kaikki joiden nimenalku on valinta*?
		valinta = document.getElementsByName('valinta');
		for(i = 0; i < valinta.length; i++)
			valinta[i].checked = true;
	}
	//Muuten tyhjennetään valinnat
	else
	{
		valinta = document.getElementsByName('valinta');
		for(i = 0; i < valinta.length; i++)
			valinta[i].checked = false;
	}
}
</script>
</head>

<body>
<p>Valitse kaikki: <input type="checkbox" id="valitse_kaikki" onclick="selection()" /></p>
<!-- Todelliset nimet valinta$id eli valinta1, valinta2 jne. -->
<p>Valinta 1: <input type="checkbox" name="valinta" /></p>
<p>Valinta 2: <input type="checkbox" name="valinta" /></p>
<p>Valinta 3: <input type="checkbox" name="valinta" /></p>
</body>

</html>

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta