Cookies op Tweakers

Tweakers is onderdeel van DPG Media en maakt gebruik van cookies, JavaScript en vergelijkbare technologie om je onder andere een optimale gebruikerservaring te bieden. Ook kan Tweakers hierdoor het gedrag van bezoekers vastleggen en analyseren. Door gebruik te maken van deze website, of door op 'Cookies accepteren' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt? Bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

[PHP] Checkboxes random in database weggeschreven

Pagina: 1
Acties:

Onderwerpen

Vraag


  • Bastiaan
  • Registratie: november 2002
  • Laatst online: 20-06 23:03

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Binnen een pagina maak ik gebruik van een form met daarin een tabel met 5 kolommen en nu 25 regels. De kolommen bestaan uit 4 input-fields en een checkbox/toggle, en is (voor het topic vereenvoudigd) als volgt opgebouwd:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<tr>
 
 <td>
 <input type="hidden" name="id[]" value="' . $row['id'] . '">
 <input type="text" class="form-control" placeholder="Registratienummer" name="registratie[]" value="' . $row['registratie'] . '">
 </td>
 
 <td>
  <input type="text" class="form-control" placeholder="Korte omschrijving" name="omschrijving_kort[]" value="' . $row['omschrijving_kort'] . '">
 </td>
 
 <td>
  <input type="text" class="form-control" placeholder="Omschrijving" name="omschrijving[]" value="' . $row['omschrijving'] . '">
 </td>
 
 <td>
  <input type="number" class="form-control" placeholder="" name="doel[]" value="' . $row['doel'] . '">
 </td>
    
 <td>
  <div class="custom-control custom-switch mt-2">
   <input type="checkbox" class="custom-control-input" name="ActiveSwitch[]" id="ActiveSwitch_' . $row['id'] . '" value="1" ' . $checked . '>
   <label class="custom-control-label" for="ActiveSwitch_' . $row['id'] . '"></label>
  </div>
 </td>
    
</tr>


Waarden en checkbox-status ($status) worden uit een MySQL-tabel gehaald en weergegeven. Eerst gesorteerd op ingeschakelde checkbox zodat de actieve bovenaan staan, en vervolgens alfabetisch op registratienummer.

Het is mogelijk om regels toe te voegen en bestaande regels te wijzigen. Deze worden met een button opgeslagen en weggeschreven naar de database. Daarvoor gebruik ik de volgende code:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if (isset($_POST['save_reg'])) {
    
 $count = count($_POST['id']);

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

 $sql = "INSERT INTO
       reg_omschrijving (`id`, `registratie`, `omschrijving_kort`, `omschrijving`, `doel`, `is_actief`)
     VALUES
      ('" . $_POST['id'][$i] . "',
      '" . $_POST['registratie'][$i] . "',
      '" . $_POST['omschrijving_kort'][$i] . "',
      '" . $_POST['omschrijving'][$i] . "',
      '" . $_POST['doel'][$i] . "',
      '" . (isset($_POST['ActiveSwitch'][$i]) ? '1' : '0') . "')
     ON DUPLICATE KEY UPDATE
      `registratie`='" . $_POST['registratie'][$i] . "',
      `omschrijving_kort`='" . $_POST['omschrijving_kort'][$i] . "',
      `omschrijving`='" . $_POST['omschrijving'][$i] . "',
      `doel`='" . $_POST['doel'][$i] . "',
      `is_actief`='" . (isset($_POST['ActiveSwitch'][$i]) ? '1' : '0') . "'
      ";

 $stmt = $db->prepare($sql);
 $stmt->execute();
  }
 }


Echter, het wegschrijven gaat alleen goed met de tekstvelden. De waarde van een aangevinkte checkbox wordt niet weggeschreven op de juiste plek, maar het lijkt die waarde lukraak weg te schrijven bij andere ID's. Pas ik bijvoorbeeld 6 checkboxen aan, worden 6 willekeurig lijkende ID's aangepast in plaats van de ID's die bij die regel horen.
De enige structuur die ik heb kunnen vinden is dat als ik checkboxen inschakel, dit bij het gelijk aantal uitgeschakelde checkboxen die bovenaan in de tabel staan wordt weggeschreven.

Voorbeeld:

code:
1
2
3
4
5
6
7
Omschrijving A | Checkbox ingeschakeld
Omschrijving D | Checkbox ingeschakeld
Omschrijving B | Checkbox uitgeschakeld
Omschrijving C | Checkbox uitgeschakeld
Omschrijving E | Checkbox uitgeschakeld
Omschrijving F | Checkbox uitgeschakeld
Omschrijving G | Checkbox uitgeschakeld


Zou ik in de deze tabel in regel #2, #5 en #7 tekst aanpassen en de checkbox van #5 en #6 aanvinken, weet ik dat de teksten die gekoppeld zijn bij die ID's goed worden aangepast. De waarden van de twee checkboxen worden weggeschreven in de ID's die gekoppeld zijn bij regels #3 en #4 (dus: de eerste twee uitgeschakelde in het formulier).
Het uitvinken van een checkbox doet ook iets soortgelijks, maar daarin kan ik niet simuleren wat en wanneer er nu precies gebeurd.

Het maakt daarbij ook niet uit of ik tijdens de query de check doe of de switch ingeschakelt is, vóór de query doe, of gewoon de $_POST['ActiveSwitch'][$i] in de query meeneem zoals ik met de andere velden doe. Ik ben door dit gedrag even de draad kwijt met waar ik het nu moet zoeken. Wie kan een zetje in de goede richting geven?

🏁 Honda CBR1000F-SS •  iPhone 11 •  MacBook Air (2015) •  TV 4K •  Watch S6 •  AirPods Pro

Beste antwoord (via Bastiaan op 15-03-2021 14:50)


  • CodeCaster
  • Registratie: juni 2003
  • Niet online

CodeCaster

👌👀 good shit ✔💯

Dat komt dus, zoals ik uitleg, doordat er geen relatie is tussen de checkboxen en het bij die regel behorende database-ID.

Je krijgt, als er 25 checkboxes op je form staan waarvan je er 4 uitvinkt, 21 checkboxes terug in je POST, en wel met de indices 0 tot en met 20. Die staan allemaal op 1. Alles daarna op 0.

Vanaf de eerste de beste uitgeschakelde (dus niet gePOSTe) checkbox, hoort $_POST['ActiveSwitch'][$i] niet meer bij $_POST['id'][$i].

Je moet dus in de checkbox-value het ID opnemen.

[Voor 4% gewijzigd door CodeCaster op 15-03-2021 14:19]

As always, we are nailed to a cross of our own construction.

Alle reacties


Acties:
  • +3Henk 'm!

  • RobIII
  • Registratie: december 2001
  • Nu online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

Heb je al eens gedebugged? Debuggen: Hoe doe ik dat?

Verder: lees je a.u.b. even in over SQL Injection; je hebt namelijk grotere problemen ;) Je gebruikt dan wel prepared statements maar je gebruikt ze verkeerd. Zie ook Over het gebruik van Parametrized Queries

[Voor 37% gewijzigd door RobIII op 15-03-2021 12:31]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij


  • Bastiaan
  • Registratie: november 2002
  • Laatst online: 20-06 23:03

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Yes, sorry, de error-reporting staat aan op de pagina zelf, maar geeft niets terug. Volledig blanco. Máák ik een error, laat de reporting wel wat zien, dus het werkt wel. Eerder had ik alleen te maken met een "Undefined offset", waardoor de if/else op de checkbox is gezet.

Qua security weet ik, maar dit is nog slechts een testinriching. Als het in de basis weer werkt wordt het uiteraard weer goed geïmplementeerd. Thanks :)

🏁 Honda CBR1000F-SS •  iPhone 11 •  MacBook Air (2015) •  TV 4K •  Watch S6 •  AirPods Pro


Acties:
  • +2Henk 'm!

  • CodeCaster
  • Registratie: juni 2003
  • Niet online

CodeCaster

👌👀 good shit ✔💯

Kijk eens in F12. Niet-gecheckte check boxes worden niet gepost.

As always, we are nailed to a cross of our own construction.


Acties:
  • +3Henk 'm!

  • RobIII
  • Registratie: december 2001
  • Nu online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

Bastiaan schreef op maandag 15 maart 2021 @ 12:33:
Yes, sorry, de error-reporting staat aan op de pagina zelf, maar geeft niets terug. Volledig blanco. Máák ik een error, laat de reporting wel wat zien, dus het werkt wel.
Debuggen is niet een kwestie van error-reporting aanzetten en klaar; daar komt (heel veel) méér bij kijken. Als je dat namelijk had gedaan had je gezien, zoals @CodeCaster aangeeft, dat niet-aangevinkte checkboxes helemaal niet gepost worden ;)
Bastiaan schreef op maandag 15 maart 2021 @ 12:33:
Qua security weet ik, maar dit is nog slechts een testinriching. Als het in de basis weer werkt wordt het uiteraard weer goed geïmplementeerd.
Beter metéén goed doen ;) Kleine (en waarschijnlijk nog minder dan nu) moeite en het wordt niet vergeten als je straks weer met iets anders door gaat en dit uit 't oog verliest.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij


  • Bastiaan
  • Registratie: november 2002
  • Laatst online: 20-06 23:03

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
CodeCaster schreef op maandag 15 maart 2021 @ 12:33:
Kijk eens in F12. Niet-gecheckte check boxes worden niet gepost.
Klopt, daarom zit er de controle of de checkbox is ge-set, en het resultaat daarvan verwacht ik dan terug te moeten zien in het op de juiste plek wegschrijven. Wellicht dat ik me nu te sterk fixeer op het verkeerde, maar mijn aandacht ging nu uit naar de onjuiste ID's waarnaar dit wordt weggeschreven, omdat de waarden an sich wel worden weggeschreven. Wijzig ik namelijk...

code:
1
isset($_POST['ActiveSwitch'][$i]) ? '1' : '0'


...naar...

code:
1
isset($_POST['ActiveSwitch'][$i]) ? 'A' : 'B'


...zie ik zowel de A-tjes als B-tjes in de database terugkomen. Ook op de verkeerde ID's, maar hé, het staat er wel :P
RobIII schreef op maandag 15 maart 2021 @ 12:36:
[...]

Debuggen is niet een kwestie van error-reporting aanzetten en klaar; daar komt (heel veel) méér bij kijken. Als je dat namelijk had gedaan had je gezien, zoals @CodeCaster aangeeft, dat niet-aangevinkte checkboxes helemaal niet gepost worden ;)


[...]

Beter metéén goed doen ;) Kleine (en waarschijnlijk nog minder dan nu) moeite en het wordt niet vergeten als je straks weer met iets anders door gaat en dit uit 't oog verliest.
Maar je hebt ook helemaal gelijk :) Deze sterk uitgeklede versie is het juist resultaat van het debuggen geweest, omdat hier de kern van het probleem zit. Dat is ook de reden dat ik extra regels, toeters, bellen en security heb losgelaten. Het was alleen niet duidelijker door me benoemd, pardon

🏁 Honda CBR1000F-SS •  iPhone 11 •  MacBook Air (2015) •  TV 4K •  Watch S6 •  AirPods Pro


  • CodeCaster
  • Registratie: juni 2003
  • Niet online

CodeCaster

👌👀 good shit ✔💯

Stel, je zet je checkboxes aan-uit-aan-uit-aan-uit, dan krijg je drie keer aan binnen op de indices 0, 1 en 2, die dan niet meer overeenkomen met de bijbehorende id's in de database.

Je kunt bijvoorbeeld het bijbehorende id in de value verwerken.

[Voor 16% gewijzigd door CodeCaster op 15-03-2021 13:23]

As always, we are nailed to a cross of our own construction.


  • Bastiaan
  • Registratie: november 2002
  • Laatst online: 20-06 23:03

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Mijn startpositie is nu alle checkboxen ingeschakeld te hebben. Daarnaast orden ik alleen op ID van 1 naar 25. Ik heb het geprobeerd zo bondig mogelijk te omschrijven, maar sit back and hold tight:
  • Zet ik de checkbox van 2, 4, 6 en 8 (willekeur) uit, worden 22, 23, 24 en 25 (de laatste vier) naar de database weggeschreven met '0'. ID 2, 4, 6 en 8 blijven gewoon op '1' staan.
  • Zet ik vervolgens 23 en 24 terug aan, worden 22 en 23 weggeschreven als '1' en staat 24 (en 25) dus toch nog als '0'.
  • Als laatst zet ik de laatste twee (24 en 25) aan, en die worden ook die weggeschreven als '1'. Nu dus weer in startpositie.
Conclusie: Het lijkt er dus op dat als ik X willekeurige checkboxen uitschakel, de X laatste ID's met ingeschakelde checkboxen uitgeschakeld.
Schakel ik Y willekeurige checkboxen in, worden de Y eerste ID's met uitgeschakelde checkboxen ingeschakeld.

Nog een ronde dan maar:
  • Zet ik de checkbox van ID 2, 4, 6 en 8 opnieuw uit, worden 22, 23, 24 en 25 weer weggeschreven met '0'.
  • Vervolgens zet ik 10, 12 en 14 ook uit, worden 19, 20 en 21 in de database aangepast naar '0'. Samengevat: nu zijn 19 t/m 25 dus uitgeschakeld.
  • Zet ik in één handeling 16 uit, 18 uit, 19 aan, 22 aan en 24 aan, staan na het wegschrijven 20 t/m 25 uitgeschakeld, en de rest ingeschakeld.
Dezelfde conclusie dan dus weer getrokken worden. Het netto aantal in- en uitgechakelde boxen klopt dus steeds wel, maar niet de corresponderende ID's.

🏁 Honda CBR1000F-SS •  iPhone 11 •  MacBook Air (2015) •  TV 4K •  Watch S6 •  AirPods Pro


Acties:
  • Beste antwoord
  • +1Henk 'm!

  • CodeCaster
  • Registratie: juni 2003
  • Niet online

CodeCaster

👌👀 good shit ✔💯

Dat komt dus, zoals ik uitleg, doordat er geen relatie is tussen de checkboxen en het bij die regel behorende database-ID.

Je krijgt, als er 25 checkboxes op je form staan waarvan je er 4 uitvinkt, 21 checkboxes terug in je POST, en wel met de indices 0 tot en met 20. Die staan allemaal op 1. Alles daarna op 0.

Vanaf de eerste de beste uitgeschakelde (dus niet gePOSTe) checkbox, hoort $_POST['ActiveSwitch'][$i] niet meer bij $_POST['id'][$i].

Je moet dus in de checkbox-value het ID opnemen.

[Voor 4% gewijzigd door CodeCaster op 15-03-2021 14:19]

As always, we are nailed to a cross of our own construction.


  • RobIII
  • Registratie: december 2001
  • Nu online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

Wat @CodeCaster zegt. Als je nou eens debugged, zoals eerder aangegeven, dan zie je vanzelf wat er mis gaat.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij


Acties:
  • +1Henk 'm!

  • Blokker_1999
  • Registratie: februari 2003
  • Laatst online: 08:15

Blokker_1999

Full steam ahead

en dit is dus waarom @RobIII reeds in zijn eerste post aangaf om te gaan debuggen. En in dit geval kan dat gewoon al vanuit je browser, zonder dat je extra tools nodig hebt. Al moet ik toegeven dat ik in dit geval de voorkeur geef aan Firefox omdat de ingebouwde devtools van Firefox netjes arrays weergeven zoals PHP ze ook zal zien, dat heb je met den standaard devtools in Chrome/Edge dan weer niet.

Als alternatief, quick and dirty, wat ik lang geleden ook wel eens deed, is gewoon mijn data dumpen helemaal bovenaan de pagina. Voeg gewoon even deze toe helemaal bovenaan je pagina:

code:
1
<pre><?php print_r($_POST); ?></pre>


Als de data die je binnenkrijgt niet de data is die je verwacht is het belangrijk om te analyseren wat je dan wel ontvangt om dan op onderzoek te gaan waarom het verwachte niet overeenkomt met de realiteit.

No keyboard detected. Press F1 to continue.


Acties:
  • +2Henk 'm!

  • AW_Bos
  • Registratie: april 2002
  • Laatst online: 09:01

AW_Bos

Waar ga je heen? ☀

Bastiaan schreef op maandag 15 maart 2021 @ 12:33:
Yes, sorry, de error-reporting staat aan op de pagina zelf, maar geeft niets terug. Volledig blanco. Máák ik een error, laat de reporting wel wat zien, dus het werkt wel. Eerder had ik alleen te maken met een "Undefined offset", waardoor de if/else op de checkbox is gezet.

Qua security weet ik, maar dit is nog slechts een testinriching. Als het in de basis weer werkt wordt het uiteraard weer goed geïmplementeerd. Thanks :)
En dan zegt RobIII
RobIII schreef op maandag 15 maart 2021 @ 12:36:
[...]

Beter metéén goed doen ;) Kleine (en waarschijnlijk nog minder dan nu) moeite en het wordt niet vergeten als je straks weer met iets anders door gaat en dit uit 't oog verliest.
En daar ga ik zeker in mee! 8)

Maarr...... SQL-injection is niet alleen het veilighouden van je query, het zorgt er ook voor dat bepaalde (gevaarlijke) karakters netjes geëscaped worden. Vul maar eens 's-Hertogenbosch als invoer in. Als je geen escaping toepast, dan zal je query direct stuklopen op de apostrof.

Als je prepared statements gebruikt, dan hoef je helemaal niet meer te escapen.

Waar ga je heen?


  • Bastiaan
  • Registratie: november 2002
  • Laatst online: 20-06 23:03

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Hey, ik ga de pro's niet tegenspreken op basis van mijn hobby-projecten en -ervaringen :P Bij een volgende keer zal ik de originele code wel gewoon laten staan.

Reden dat het niet in mijn post stond was dit:
Bastiaan schreef op maandag 15 maart 2021 @ 13:05:
[...]

Maar je hebt ook helemaal gelijk :) Deze sterk uitgeklede versie is het juist resultaat van het debuggen geweest, omdat hier de kern van het probleem zit. Dat is ook de reden dat ik extra regels, toeters, bellen en security heb losgelaten. Het was alleen niet duidelijker door me benoemd, pardon
Alles was juist in het proces geschrapt om uit te sluiten dat daar iets niet goed zat. Achteraf is het de koe in de kont kijken, maar oké. In mijn beleving tot gistermiddag werd in iedere loop de waarde opnieuw al dan niet uitgelezen. Daarbij had ik alleen geen rekening gehouden met dat het hebben van geen waarde ervoor zorgt dat data gaat schuiven, want: "bij iedere nieuwe loop begint het valideren van de waarden in een rij toch helemaal opnieuw en wordt iedere regel weer vers ingelezen en weggeschreven", was mijn veronderstelling.

In de (privé) ontwikkel- en productie-omgevingen is het dus gewoon netjes ingericht met prepared statements, zoals het behoort :)

🏁 Honda CBR1000F-SS •  iPhone 11 •  MacBook Air (2015) •  TV 4K •  Watch S6 •  AirPods Pro

Pagina: 1


Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Microsoft Xbox Series X LG CX Google Pixel 5a 5G Sony XH90 / XH92 Samsung Galaxy S21 5G Sony PlayStation 5 Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True