[PHP/MySQL]Array van PHP bij where id IN ([ARRAY])

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • HyperBart
  • Registratie: Maart 2006
  • Laatst online: 23:26
Een beknopte titel, waar ik het volgende mee wil vragen:

Is het mogelijk (en zo ja, hoe dan eigenlijk, want google gaf me niet het antwoord of ik gebruikte foute termen) om bij een update of delete of eender welk statement het volgende te kunnen fixen:

MySQL:
1
UPDATE inschrijvingen SET betaald = 1 WHERE userid IN [USERID's]


waarbij dat in [USERID's] alle ID's zitten van een groep geselecteerden die doorgestuurd is vanuit een form met checkboxes.

Als je het achterliggende verhaal wil kennen:

een user moet met checkboxes kunnen aanduiden wie allemaal ingeschreven is (dus dan een record aanmaken in de tabel) met een checkbox en of ie betaald heeft met een tweede checkbox.

Mijn idee was om bij de inschrijvingen het als volgt te doen:
MySQL:
1
DELETE alle inschrijvingen WHERE userid not in [USERID's]

zodat alle inschrijvingen verwijderd worden die in de DB zaten en die dus nu uitgevinkt zijn of nooit aangevinkt zijn geweest

vervolgens met een for-lus de array doen doorlopen, als de inschrijving met het huidige id van de array al bestaat moet er niets gebeuren, anders moet het aangemaakt worden.

Voor betaald volgen we hetzelfde systeem als hierboven en komt er nog een extra controle bij met een functie die een inschrijving aanmaakt als ze nog niet bestaat en als ze al bestaat ze gewoon op betaald wordt gezet.

Tot zover, ik heb er al fel over nagedacht, maar ik kwam niet echt tot een oplossing, raad en advies over hoe dit makkelijker kan in OO-PHP mag natuurlijk altijd, ik zit er vaak over na te denken en had hier deze denkwijze net bedacht op de fiets 8)7 .

Acties:
  • 0 Henk 'm!

  • Ricvdp
  • Registratie: Juni 2005
  • Laatst online: 22-09 09:44
implode() gebruiken op je array, en op deze manier alle items uit je array in de query zetten? Of denk ik nou te makkelijk? Iets als "SELECT blaat FROM users WHERE id IN (".implode(',', $array).")";

Acties:
  • 0 Henk 'm!

  • HyperBart
  • Registratie: Maart 2006
  • Laatst online: 23:26
wel, ik dacht eigenlijk net ook dat het gewoon een string moet zijn die in dat sql statement staat, dus implode zou goed vanpas komen daarbij... :o

Simpele dingen, vaak de beste... Andere ideeën zijn ook nog welkom... (voor het hele verhaal dan)

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Als je inderdaad implode gebruikt op data die uit checkboxes komt: vergeet niet om er eerst zeker van te zijn dat het allemaal integer zijn die je erin stopt. SQL injectie in dit soort queries is iets waar vaak niet aan gedacht wordt. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • JWolters
  • Registratie: Maart 2001
  • Laatst online: 22-09 17:14

JWolters

Killing Me Killing You

Check van te voren wel of er ook echt iets aangevinkt is/elementen in je array staan anders krijg je een SQL-error.

Time is my only fear, an enemy of Sand


Acties:
  • 0 Henk 'm!

Verwijderd

Ik ben nog niet zo heel lang bezig met php maar misschien dat dit een oplossing is of iets richting de goede weg

in het formulier script

$result = mysql_query("SELECT id, name FROM mytable");

while ($row = mysql_fetch_array($result)) { #maakt voor iedereen een checkbox aan.
echo('<input type="checkbox" name="'.$row['id].'" value="1"> betaald'.$row['naam']);
$totaal=$row['id'];
}

in het controle script

while (!$stop==$_POST['totaal']) { #als hij bij het laatste id is geweest dan stopt hij.
$i++
if (empty($_POST['id'])){
}elseif($_POST[$i]==1){
mysql_query('UPDATE inschrijvingen SET betaald = 1 WHERE userid = '.$i);
}elseif(!$_POST[$i]==1){
mysql_query('DELETE from inschrijvingen WHERE userid ='.$i);
}
$stop=$i;
}

misschien dat dit kan helpen.

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Negeer aub bovenstaande code, want daar staan echt te veel fouten in. Om een voorbeeldje te noemen: De controle loop conditie op basis van een user input is echt te pover. Door de 'totaal' parameter te wijzigen kan je te weinig iteraties forceren, of -wellicht nog leuker- een eeuwige loop.

{signature}


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Verwijderd schreef op dinsdag 21 april 2009 @ 09:10:
Ik ben nog niet zo heel lang bezig met php maar misschien dat dit een oplossing is of iets richting de goede weg

in het formulier script

$result = mysql_query("SELECT id, name FROM mytable");

while ($row = mysql_fetch_array($result)) { #maakt voor iedereen een checkbox aan.
echo('<input type="checkbox" name="'.$row['id].'" value="1"> betaald'.$row['naam']);
$totaal=$row['id'];
}

in het controle script

while (!$stop==$_POST['totaal']) { #als hij bij het laatste id is geweest dan stopt hij.
$i++
if (empty($_POST['id'])){
}elseif($_POST[$i]==1){
mysql_query('UPDATE inschrijvingen SET betaald = 1 WHERE userid = '.$i);
}elseif(!$_POST[$i]==1){
mysql_query('DELETE from inschrijvingen WHERE userid ='.$i);
}
$stop=$i;
}

misschien dat dit kan helpen.
Leuk, maar er zitten een aantal problemen in:

* Voor elke gebruiker wordt een aparte query uitgevoerd - de TS weet de SQL om het allemaal in een keer te doen.

* $_POST[$i] hoeft in dit geval niet een user ID / checkbox te zijn, en kan alles zijn.

* Je eerste if doet niks

* Je stop-conditie is nogal vaag opgebouwd - je zou in dit voorbeeld ook while(!empty($_POST[$i++]))) { kunnen doen, om maar een voorbeeld te geven - niet dat het zo zou moeten, overigens.

Maar dit is nauwelijks het topic om opmerkingen op andermans code te geven. Een oplossing werd eerder al gegeven, daar kan ik ook verder niks nuttigs meer aan toevoegen.

Acties:
  • 0 Henk 'm!

  • HyperBart
  • Registratie: Maart 2006
  • Laatst online: 23:26
NMe schreef op dinsdag 21 april 2009 @ 01:27:
Als je inderdaad implode gebruikt op data die uit checkboxes komt: vergeet niet om er eerst zeker van te zijn dat het allemaal integer zijn die je erin stopt. SQL injectie in dit soort queries is iets waar vaak niet aan gedacht wordt. :)
Ik denk dat ik een toNull functie heb die automatisch quotes toevoegd rond alles, maar ik check het even, bedankt voor de tip !
JWolters schreef op dinsdag 21 april 2009 @ 08:34:
Check van te voren wel of er ook echt iets aangevinkt is/elementen in je array staan anders krijg je een SQL-error.
Doe ik, als ik niets heb aangevinkt worden alle inschrijvingen die bij een activiteit horen gedeleted...

Acties:
  • 0 Henk 'm!

  • trinite_t
  • Registratie: Maart 2003
  • Laatst online: 22-09 13:25
HyperBart schreef op dinsdag 21 april 2009 @ 11:22:
Ik denk dat ik een toNull functie heb die automatisch quotes toevoegd rond alles, maar ik check het even, bedankt voor de tip !
Ik zou gewoon alle waardes in het array, als het toch ints zijn, casten naar integers. Verkeerde waardes worden dan 0.

voor de zekerheid:
PHP:
1
$arr[0] = (int)$arr[0];

[ Voor 60% gewijzigd door trinite_t op 21-04-2009 11:30 ]

The easiest way to solve a problem is just to solve it.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

HyperBart schreef op dinsdag 21 april 2009 @ 11:22:
[...]

Ik denk dat ik een toNull functie heb die automatisch quotes toevoegd rond alles, maar ik check het even, bedankt voor de tip !
Ok, en wat als ik dan als id doorgeef: 0') OR userid > 0 OR userid IN ('0. Overal blind quotes omheen zetten lost niks op en maakt je code alsnog onveilig. Bovenstaande "id" levert namelijk de volgende query op voor je delete:
SQL:
1
DELETE FROM inschrijvingen WHERE userid not in ('0') OR userid > 0 OR userid IN ('0')

Tada, lege table. ;)
trinite_t schreef op dinsdag 21 april 2009 @ 11:26:
[...]

Ik zou gewoon alle waardes in het array, als het toch ints zijn, casten naar integers. Verkeerde waardes worden dan 0.

voor de zekerheid:
PHP:
1
$arr[0] = (int)$arr[0];
Kijk nog eens naar die delete query. Delete from ... where id not in (0) lijkt me niet per se handig. :P

[ Voor 25% gewijzigd door NMe op 21-04-2009 11:33 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • trinite_t
  • Registratie: Maart 2003
  • Laatst online: 22-09 13:25
NMe schreef op dinsdag 21 april 2009 @ 11:32:
Kijk nog eens naar die delete query. Delete from ... where id not in (0) lijkt me niet per se handig. :P
aargh, je hebt gelijk, mss ook even kijken of er dan ook werkelijk wat ingevuld is ;)

The easiest way to solve a problem is just to solve it.


Acties:
  • 0 Henk 'm!

  • HyperBart
  • Registratie: Maart 2006
  • Laatst online: 23:26
Ik bedoel een escape functie en die maakte van alle ongewenste ' een \' ofzoiets, dat hadden we op school geleerd.

Dit is trouwens een projectje voor school, ik zoek het straks nog even uit, nu terug wat les volgen ;)

Acties:
  • 0 Henk 'm!

  • trinite_t
  • Registratie: Maart 2003
  • Laatst online: 22-09 13:25
Als je alleen ints als input heb zou ik geen escape functie gebruiken. Plus dat je voor ints geen ' nodig hebt.

The easiest way to solve a problem is just to solve it.


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
HyperBart schreef op dinsdag 21 april 2009 @ 11:41:
Ik bedoel een escape functie en die maakte van alle ongewenste ' een \' ofzoiets, dat hadden we op school geleerd.

Dit is trouwens een projectje voor school, ik zoek het straks nog even uit, nu terug wat les volgen ;)
Ja maar hoe nuttig is het om
SQL:
1
2
DELETE FROM tabel
WHERE myID not in ( '0\' some SQL injection' )

te doen. Het is beter om te controleren dat de data die je binnenkrijgt aan je verwachtingen voldoet.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • HyperBart
  • Registratie: Maart 2006
  • Laatst online: 23:26
Maar het vangt die sql injectie toch op, niet ?

edit: ik volg nu even niet meer; op welke manier kan je die dan controleren ?

[ Voor 46% gewijzigd door HyperBart op 21-04-2009 11:48 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

HyperBart schreef op dinsdag 21 april 2009 @ 11:47:
Maar het vangt die sql injectie toch op, niet ?

edit: ik volg nu even niet meer; op welke manier kan je die dan controleren ?
Integers zijn geen strings en ze gewoon tóch tussen quotes zetten is nogal lomp. Dan kun je beter eerst door je array heen lopen en alle items droppen die geen cijfer zijn voordat je je implode doet. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • fleppuhstein
  • Registratie: Januari 2002
  • Laatst online: 07-09 13:37
Waarom niet kiezen voor een nette OO manier. Een user object is wel een basis OO principe. Vervolgens schrijf je netjes een aantal methods die overeen komen met je wensen. Hierdoor heb je wel meer queries, maar wel queries die optimaler zijn.

UPDATE inschrijvingen SET betaald = 1 WHERE userid IN [USERID's] is een dure query omdat je IN gebruikt. Terwijl een = goedkoper is. De IN is namelijk een string comparisent operatie.

Verder vraag ik mij nog af hoe je database model eruit ziet, omdat je delete queries wil uitvoeren. Iemand die dus geen inschrijving heeft staat niet in de tabel, en zal dus leeg resultaat opleveren in een qeury bij het gebruik van join.

Denk nog eens een beetje na over je datamodel en je OO objecten en methods / properties.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
fleppuhstein schreef op dinsdag 21 april 2009 @ 13:40:
Waarom niet kiezen voor een nette OO manier. Een user object is wel een basis OO principe. Vervolgens schrijf je netjes een aantal methods die overeen komen met je wensen. Hierdoor heb je wel meer queries, maar wel queries die optimaler zijn.
Wat heeft OO er mee te maken of query's optimaal zijn? Voor hetzelfde geld gebruik je een OR mapper die ook deletes batched en gewoon gebruik maakt van een IN operator.
fleppuhstein schreef op dinsdag 21 april 2009 @ 13:40:
UPDATE inschrijvingen SET betaald = 1 WHERE userid IN [USERID's] is een dure query omdat je IN gebruikt. Terwijl een = goedkoper is. De IN is namelijk een string comparisent operatie.
Een IN is natuurlijk een stuk "goedkoper" dan voor elke id een aparte query. En het is ook totaal niet waar dan IN een string compare is. Ben je niet in de de war met MATCH AGAINST, en dus Full Text Indexing?
Denk nog eens een beetje na over je datamodel en je OO objecten en methods / properties.
Er is in het topic zo goed als niks over het datamodel gezegd, maar in de TS gaat het over het updaten van een Betaald flag, daar vind ik niks bijzonders aan waardoor ik zou gaan denken dat het datamodel compleet verkeerd is.

[ Voor 58% gewijzigd door Woy op 21-04-2009 14:32 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Naast wat Woy zegt, een query als

code:
1
UPDATE x WHERE y IN (42)


wordt toch wel door de optimizer herschreven als

code:
1
UPDATE x WHERE y = 42


als het maar 1 item betreft.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • HyperBart
  • Registratie: Maart 2006
  • Laatst online: 23:26
fleppuhstein schreef op dinsdag 21 april 2009 @ 13:40:
Verder vraag ik mij nog af hoe je database model eruit ziet, omdat je delete queries wil uitvoeren. Iemand die dus geen inschrijving heeft staat niet in de tabel, en zal dus leeg resultaat opleveren in een qeury bij het gebruik van join.
:?
Ik heb een tabel gebruikers, activiteiten en inschrijvingen, en logischerwijs is inschrijvingen een koppeling tussen gebruikers en activiteiten. Ik zie niet echt een probleem met mijn data-model ?
Pagina: 1