WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   php loop formulär variabler problem (https://www.wn.se/forum/showthread.php?t=1038359)

Fia 2009-10-05 13:53

php loop formulär variabler problem
 
Hej!

Jag tor jag har målat in mig i en hörna lite gran och vill höra om der fins någon som har ett förslag. Jag har i ett formulär loopat fram en serie fält.

for ( $x=1; $x <= 8; $x ++) {
echo'
<input type="text" name="ingrediens'.$x.'" style="width:165px;height:13px;margin:2px;"/><br>
';}

sen vill jag loopa igenom dem igen när formen är skickad för att se om de är i fyllda och är de ifyllda ska de läggas i i DB. Hur får jag fram värdet i variablen $ingrediens1 till $ingrediens8 undrar jag då. Jag har extract $_POST.

for ( $x=1; $x <= 8; $x ++) {

$xingrediens=$ingrediens.$x; //problemet.........

if(!empty($xingrediens)){
$sql = "INSERT INTO tblIngrediens SET ingrediens='$xingrediens'";
mysql_query($sql) or die("Det har uppstått ett fel:" . mysql_error());
}//end if
}//end for loop

Är jag på helt fel spår eller?

BjörnJ 2009-10-05 14:01

Citat:

Ursprungligen postat av Fia (Inlägg 20324831)
$xingrediens=$ingrediens.$x; //problemet.........

$xingrediens=$_POST['ingrediens'.$x];

Citat:

Ursprungligen postat av Fia (Inlägg 20324831)
$sql = "INSERT INTO tblIngrediens SET ingrediens='$xingrediens'";
mysql_query($sql) or die("Det har uppstått ett fel:" . mysql_error());

Livsfarligt.

$sql = "INSERT INTO tblIngrediens SET ingrediens='".mysql_real_escape_string($xingredien s)."'";

Fia 2009-10-05 14:08

Tack för svaret
Varför är det Livsfarligt? vad gör mysql_real_escape_string.

dotvoid 2009-10-05 14:22

Det finns lyckligtvis bättre sätt att jobba med många fält. Du kan ha input-fält med samma namn deklarerat som en array.
<form>
<input type="text" name="ingrediens[]">
<input type="text" name="ingrediens[]">
<input type="text" name="ingrediens[]">
</form>

foreach ($_POST['ingrediens'] as $value) {
// Gör vad du ska med ingrediensen som nu är i $value. Exempelvis
if (trim($value) != '') {
$value = mysql_real_escape_string($value);
// Skapa insert/update/whatever
}
}

Mysql-api:et är kanske inte det optimala heller. Kolla mysqli-apiet eller PDO. Om du loopande ska lägga in data i en databas borde du också förbereda (prepare) ett sql-statement som då får bättre prestanda och slipper riskera att missa mysql_real_escape_string edy.

Exempel med PDO mot MySQL:

$dsn = 'mysql:dbname=receptdb;host=localhost';
$dbUser = 'receptanv';
$dbPassword = 'hemligtlösenord';

$dbh = new PDO($dsn, $dbUser, $dbPassword);

$stmt = $dbh->prepare('INSERT tblIngrediens (ingrediens) VALUES(:ingrediens)';
foreach ($_POST['ingrediens'] as $value) {
$stmt->execute(array(':ingrediens', trim($value));
}

Sen antar jag att du i verkligheten har en del annat som kopplar ihop ingredienserna mot ett recept. Men det lägger inte jag mig i ;)

Innan du fortsätter så läs mer om PDO på http://se2.php.net/manual/en/book.pdo.php

dotvoid 2009-10-05 14:26

Utan att vara elak är det lite läskigt att du behöver fråga om vad mysql_real_escape_string() gör eller varför din kod ovan är farlig. Du behöver troligen läsa på lite om sql injections och säkerhet så slipper du problem i framtiden.

Men kör med PDO och prepared statements enligt ovan så är du mer säker.

Fia 2009-10-05 14:28

Ska jag göra, jag får läsa på lite imorgon. Tack för hjälpen.

BjörnJ 2009-10-05 14:29

Om man skickar data angiven av användare rakt in i databasen går det att utifrån skicka vilka kommandon man vill till databasen.

T.ex. om någon skriver följande i formuläret:
'; DELETE FROM tblIngrediens WHERE 'a'='a

Så kommer följande skickas till databasen:
INSERT INTO tblIngrediens SET ingrediens=''; DELETE FROM tblIngrediens WHERE 'a'='a'

Det kallas SQL injection.
http://en.wikipedia.org/wiki/SQL_injection

mysql_real_escape_string() byter ut t.ex. ' mot \' så att databasen vet att ' är en del av texten, och inte avslut på strängen.

Man bör absolut använda mysql_real_escape_string() även om det bara är admin som har tillgång till formuläret.

Tillägg:
Se även http://se2.php.net/manual/en/functio...ape-string.php

dotvoid 2009-10-05 14:34

Bra sammanfattning. Jag brukar dock använda mig av pdo:s prepared statements enligt ovan. Då görs detta automatiskt när värden binds mot sql-satsens platshållare. Om man inte använder prepared statements så används pdo:s quote(). Enligt exemplet ovan:

$dbh = new PDO($dsn, $dbUser, $dbPassword);
$quoted_value = $dbh->quote($value);

tartareandesire 2009-10-05 14:44

Citat:

Ursprungligen postat av dotvoid (Inlägg 20324848)
Bra sammanfattning. Jag brukar dock använda mig av pdo:s prepared statements enligt ovan. Då görs detta automatiskt när värden binds mot sql-satsens platshållare. Om man inte använder prepared statements så används pdo:s quote(). Enligt exemplet ovan:

$dbh = new PDO($dsn, $dbUser, $dbPassword);
$quoted_value = $dbh->quote($value);

Det spelar ju inte så stor roll vilken metod man använder, i vilket fall som helst måste man komma ihåg att använda den =)

Tycker det är lite överdrivet att säga att det är läskigt att Fia inte har koll på säkerheten. Att inte tänka på säkerheten är ett av de absolut vanligaste misstagen nybörjare gör, oavsett språk. Det är ingenting de flesta bryr sig om i början och det kanske inte är så allvarligt egentligen.

Fia, lek lite med koden och ha kul och börja sedan läsa på om säkerheten när du känner att du vill börja programmera lite mer på allvar. Det finns mer än bara sql injections du bör tänka på då.

dotvoid 2009-10-05 15:12

Dålig formulering från min sida kanske. Jag sa ju att jag inte var elak. Däremot är det ett stort problem att alla tutorials för nybörjare totalt ignorerar säkerhet. Det är inte nybörjarnas fel.

Jo metoden spelar roll. Använder du konsekvent prepared statements i PDO så slipper du komma ihåg saker som mysql_real_escape_string() på varje inkommande variabel, vare sig det är saker som kommer genom $_GET, $_POST, $_COOKIE eller $_SERVER eller från annan källa.

Det är väl ett plus om något! Det gäller att välja rätt väg från början så att man kan vara lite lat :) Därför la jag också med ett komplett exempel på hur man går tillväga med PDO:s prepared statements.

Åt andra hållet ska man alltid använda htmlspecialchars() m fl metoder innan man visar data som kommer från extern källa på en webbsida.

Att första leka lite och sen tänka på säkerheten gör det kanske lite roligare i i början men är kanske inte alltid så bra. Det är faktiskt bara några enkla regler man behöver ha i åtanke för att täcka det mesta - inte allt men det viktigaste. Gör man det från början är man såå tacksam när man ska mecka i sina gamla grejer som börjat leva sina egna liv.

Bra vanor grundlägger man inte genom att börja med slarv ;)

Reager 2009-10-05 16:30

Om inte SQL när man använder PHP skiljer sig från vanlig SQL så kan det vara värt att påpeka att det är felaktig SQL oxå.

$sql = "INSERT INTO tblIngrediens SET ingrediens='$xingrediens'";

Ser ut som en blandning mellan INSERT och UPDATE. Den korrekta bör väl vara

$sql = "INSERT INTO tblIngrediens VALUES('" . $xingrediens ."')";

Såg inte att någon påpekat detta tidigare och det kan ju vara bra att veta :)

tartareandesire 2009-10-05 16:43

Citat:

Ursprungligen postat av Reager (Inlägg 20324869)
Om inte SQL när man använder PHP skiljer sig från vanlig SQL så kan det vara värt att påpeka att det är felaktig SQL oxå.

$sql = "INSERT INTO tblIngrediens SET ingrediens='$xingrediens'";

Ser ut som en blandning mellan INSERT och UPDATE. Den korrekta bör väl vara

$sql = "INSERT INTO tblIngrediens VALUES('" . $xingrediens ."')";

Såg inte att någon påpekat detta tidigare och det kan ju vara bra att veta :)

Det går alldeles utmärkt att köra "update"-varianten också om man kör MySQL (PHP har inget med saken att göra) vilken jag själv rekommenderar då koden blir mer logisk och lättläst.

Nerox 2009-10-05 18:52

Citat:

Ursprungligen postat av Reager (Inlägg 20324869)
Om inte SQL när man använder PHP skiljer sig från vanlig SQL så kan det vara värt att påpeka att det är felaktig SQL oxå.

$sql = "INSERT INTO tblIngrediens SET ingrediens='$xingrediens'";

Ser ut som en blandning mellan INSERT och UPDATE. Den korrekta bör väl vara

$sql = "INSERT INTO tblIngrediens VALUES('" . $xingrediens ."')";

Såg inte att någon påpekat detta tidigare och det kan ju vara bra att veta :)

Ska man vara petig ska du väll ha deklarerat vilke kolumner du sätte in värden i med

Kod:

$sql = "INSERT INTO tblIngrediens (ingridiens)VALUES('" . $xingrediens ."')";

Fia 2009-10-06 08:47

Jag har använt denna vid formulär inlägg till DB, går inte det lika bra?

function addslashes_deep($value)
{
$value = is_array($value) ?
array_map('addslashes_deep', $value) :
addslashes($value);
return $value;
}

också strippar jag det med en liknande function när jag hämtar det.

dotvoid 2009-10-06 09:05

Som tartareandesire påpekar går det lika bra att använda INSERT...SET-syntaxen så länge man håller sig till MySQL. Ska du byta databas blir det jobbigare eftersom det inte följer SQL-standard(er). Men ärligt talat - hur ofta byter man databas? (Själv skulle jag iofs undvika just den syntaxen.)

Funktionen addslashes() är inte lika bra. Den har problem med multibyte-characters t ex. Till och med dokumentationen, http://se2.php.net/addslashes, säger att man bör använda mysql_real_escape_string() eller motsvarande för andra databaser istället för addslashes().

Jag har hört att addslashes() ska droppas från PHP6 men jag har inte kollat upp det själv.

Fia 2009-10-06 09:14

Synd det var så smidigt att bara lägga functionen på $POST nu måste man ju gå in på varje sträng som ska in och lägga till mysql_real_escape_string(). Då har jag syselsättnig idag i alla fall.......
Eller skulle man kunna byta ut addslashes() mot mysql_escape_string() i functionen, Bara spånar lite, det får jag prova. Tack för all lärorik information.

dotvoid 2009-10-06 09:31

Ja du skulle kunna byta ut addslashes() mot mysql_real_escape_string(). (Tänk bara på att databaskopplingen redan måste vara etablerad för att mysql_real_escape_string() ska fungera.)

Fia 2009-10-06 09:49

Så här blev det.
function addslashes_deep($value)
{
$value = is_array($value) ?
array_map('addslashes_deep', $value) :
mysql_real_escape_string(trim($value));
return $value;
}

Så kör jag den här
$_POST = addslashes_deep($_POST);

Och vill man bli av med html oxå så

mysql_real_escape_string(strip_tags(trim($value))) ;

danjel 2009-10-06 14:42

Tänk på att man man kanske vill använda $_POST variabler till annat än DB frågor efter att du kört addslashes_deep , tex skriva ut värden, maila eller liknande , så undvik helst denna princip framöver..
Som någon har sagt säkert redan i tråden, kör pdo prepared statements så slipper man alls bekymra sig om detta säkerhetshål

tartareandesire 2009-10-06 15:25

Citat:

Ursprungligen postat av danjel (Inlägg 20325038)
Tänk på att man man kanske vill använda $_POST variabler till annat än DB frågor efter att du kört addslashes_deep , tex skriva ut värden, maila eller liknande , så undvik helst denna princip framöver..
Som någon har sagt säkert redan i tråden, kör pdo prepared statements så slipper man alls bekymra sig om detta säkerhetshål

Det går ju att tilldela andra variabler för det som behövs skrivas ut i så fall.

Nerox 2009-10-06 16:17

Citat:

Ursprungligen postat av dotvoid (Inlägg 20324989)
Som tartareandesire påpekar går det lika bra att använda INSERT...SET-syntaxen så länge man håller sig till MySQL. Ska du byta databas blir det jobbigare eftersom det inte följer SQL-standard(er). Men ärligt talat - hur ofta byter man databas? (Själv skulle jag iofs undvika just den syntaxen.


Alla bör köra med den syntaxen dom tycker underlättar just deras kodande. Dock gör jag projekt nån annan skall koda på senare försöker jag hålla strikt standard just av den anledningen att det är standard och underlättar för nästa person då denna med all sannolikhet känner till standarden.

danjel 2009-10-06 17:26

Citat:

Ursprungligen postat av tartareandesire (Inlägg 20325043)
Det går ju att tilldela andra variabler för det som behövs skrivas ut i så fall.

Jo såklart men det känns onödigt att "escapa" allt POST data när inte ens allt kanske ska in i databasen..speciellt då detta inte ens är nödvändigt med PDO

dotvoid 2009-10-06 22:32

Citat:

Ursprungligen postat av Nerox (Inlägg 20325052)
Alla bör köra med den syntaxen dom tycker underlättar just deras kodande.

Det håller jag inte med om. När man börjar lära sig bör man lära sig standarder och vedertagen praxis. Först när man kan reglerna så bra att man vet när och varför det är lämpligt att använda icke-standarder eller bryta mot praxis kan man överväga det.

Det blir lättare att läsa andras kod för att lära sig. Det är lättare att få hjälp. Det är lättare att hjälpa. Det är lättare att byta teknikplattform.

Och sist men inte minst, man slipper de alltför vanliga problemen med att tillverkar-specifik syntax och teknik blir obsolet. Därmed blir det å så mycket lättare att uppgradera sina projekt till nyare PHP- och MySQL-versioner (t ex) i framtiden.

dotvoid 2009-10-06 22:33

Citat:

Ursprungligen postat av danjel (Inlägg 20325068)
Jo såklart men det känns onödigt att "escapa" allt POST data när inte ens allt kanske ska in i databasen..speciellt då detta inte ens är nödvändigt med PDO

Mestadels tycke och smak även om jag håller med dig i sak ;)


Alla tider är GMT +2. Klockan är nu 15:13.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson