[MySQL] foreach schrijft naar adresbalk ipv database

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Bastiaan
  • Registratie: November 2002
  • Laatst online: 12:39

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Als hobbyist vind ik het lekker om dágen te slijten met code kloppen om voor privé-doeleinden web-apps in elkaar te kunnen zetten.

Dat gaat me inmiddels goed af. Met alle documentatie via Google en andere fora kan ik de meeste problemen die ik tegenkom ook gewoon de baas. Van scratch wat beginnen te kloppen is niet mijn ding, maar ik kan wel een lap aan code lezen, begrijpen wat het doet, en bijvoorbeeld relevante regels pakken en ombouwen naar de situatie die ik zoek. Ik loop nu alleen tegen een probleem aan dat ik met deze manier van werken niet opgelost krijg, en dat heeft te maken met het schrijven naar de database met daarin een foreach-statement.

Ik heb een document waarop 30+ regels staan, iedere regel met 7 invoervelden. Om de oorzaak van het probleem te begrijpen heb ik nu die output beperkt tot alleen een output met de volgende drie (voor dit topic vergemakkelijkte) velden:

code:
1
2
3
<input type="hidden" name="id" value="$id">
<input type="text" class="form-control" name="invoerveld_a" value="$waarde_a">
<input type="text" class="form-control" name="invoerveld_b" value="$waarde_b">


Deze lijst met velden wordt ook door middel van een foreach uit een database gehaald en foutloos weergegeven. Ik zie dus alle regels bestaande uit 2 zichtbare en 1 verborgen kolom, met daarin ook de juiste waarden. Het idee is nu dat ik waarden kan aanpassen en deze kan opslaan.

Het ophalen van de waarden lukt met twee vingers in de neus. Mijn logisch verstand zegt daarom dat met wat aanpassen, trials en errors het ook wel moet lukken om de basis van die query te gebruiken voor het wegschrijven van alle velden. Wat ik nu heb staan is het volgende:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if ($_POST['submit_form']) {

$data = [
  'id' => $POST['id'],
  'waarde_a' => htmlspecialchars($_POST['invoerveld_a'] ?? '', ENT_QUOTES),
  'waarde_b' => htmlspecialchars($_POST['invoerveld_b'] ?? '', ENT_QUOTES),
];

$sql = "UPDATE table SET waarde_a=:waarde_a, waarde_b=:waarde_b WHERE id=:id";

foreach ($data as $key => $value) {
  $stmt = $pdo->prepare($sql);
  $stmt->execute($data);
}
}

De theorie is dat bij het klikken op een save-button de data moet worden opgeslagen. Deze werkwijze van gegevensopslag (dus: zonder een array) werkt overigens wanneer ik dit gebruik binnen formulieren met unieke names voor de velden. Waar het hier mis gaat is dat er wel iets leek te gebeuren, maar er niets in de database verandert. Nu blijkt later (lang leve het beperken van de zichtbare URL-lengte) dat de hele string mét gewijzigde data in de adresbalk staat:

code:
1
2
3
/document.php?submit_form=update
&id=1&waarde_a=nieuwe_output_invoerveld_1a&waarde_b=nieuwe_output_invoerveld_1b
&id=2&waarde_a=nieuwe_output_invoerveld_2a&waarde_b=nieuwe_output_invoerveld_2b


Daaruit maak ik op dat in principe de query een beetje klopt. De data wordt tenslotte opgepakt en ergens uitgespuugd, maar niet op de juiste plek.

Niet gehinderd door gebrek aan kennis van het op deze manier wegschrijven weet ik even niet waar ik nu verder moet zoeken. Met name op Stackoverflow heb ik veel informatie kunnen halen, maar niet een oplossing voor dit specifieke probleem. De topics die ik vond gaan over het volledig niet weg kunnen schrijven. Ik ben ook bezig geweest met andere manieren van wegschrijven (zelfde principe, maar bijvoorbeeld andere volgorde of manieren van binden), maar die zorgen allemaal voor ditzelfde resultaat. Wat het vooral moeilijk maakt is dat de error reporting is ingeschakeld (E_ALL), maar er op dit punt helemaal géén errors verschijnen.

Is er iemand die me kan vertellen waarom dit verwerkt wordt zoals het nu gaat? Op welk punt moet ik me focussen om het op te lossen?

Beste antwoord (via Bastiaan op 29-08-2020 13:06)


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Bastiaan schreef op zaterdag 29 augustus 2020 @ 11:45:
[...]

Yes, dat weet het form. Op andere plekken in de testomgeving worden velden op dezelfde manier trouwens wel succesvol weggeschreven, dus de post-config zou oké moeten zijn, maar dat zijn dan ook allemaal velden met unieke namen.
Als alle velden in je adresbalk komen staan dan wordt er een GET uitgevoerd en geen POST. Basta. Dus dan zit daar iets mis.
Bastiaan schreef op zaterdag 29 augustus 2020 @ 11:45:
Dank je! Heb ik voor de goede orde gecorrigeerd.
Heb je mijn edit m.b.t. je foreach ook gezien?

[ Voor 18% gewijzigd door RobIII op 29-08-2020 11:46 ]

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

Je eigen tweaker.me redirect

Over mij

Alle reacties


Acties:
  • +2 Henk 'm!

  • Feanathiel
  • Registratie: Juni 2007
  • Niet online

Feanathiel

Cup<Coffee>

Weet de form dat hij moest POST'en (<form method="POST">)? Als je 'm weg laat, dan is de standaard methode 'GET' waardoor vervolgens alle waarden in de url worden meegegeven.

[ Voor 3% gewijzigd door Feanathiel op 29-08-2020 11:38 ]


Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
^ Wat hij zegt. Maar nog een tip: htmlspecialchars gebruik je aan de output kant (dus in je template / "bij je echo's") en niet als je zaken in de DB zet. Wat als je straks die data in een andere context dan een HTML pagina (bijvoorbeeld in een PDF, adressticker, Excel export, whateverdefuck) wil gebruiken? Dan zit je met allemaal html-escaped zooi in je DB. Dat moet je nooit doen. Escaping regel je altijd aan de output kant.

Verder snap ik je foreach niet... je voert nu 3x de query uit? Why :?

[ Voor 51% gewijzigd door RobIII op 29-08-2020 11:44 ]

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

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Bastiaan
  • Registratie: November 2002
  • Laatst online: 12:39

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Feanathiel schreef op zaterdag 29 augustus 2020 @ 11:38:
Weet de form dat hij moest POST'en (<form method="POST">)? Als je 'm weg laat, dan is de standaard methode 'GET' waardoor vervolgens alle waarden in de url worden meegegeven.
Yes, dat weet het form. Op andere plekken in de testomgeving worden velden op dezelfde manier trouwens wel succesvol weggeschreven, dus de post-config zou oké moeten zijn, maar dat zijn dan ook allemaal velden met unieke namen.
RobIII schreef op zaterdag 29 augustus 2020 @ 11:40:
^ Wat hij zegt. Maar nog een tip: htmlspecialchars gebruik je aan de output kant (dus in je template / "bij je echo's") en niet als je zaken in de DB zet. Wat als je straks die data in een andere context dan een HTML pagina (bijvoorbeeld in een PDF, adressticker, Excel export, whateverdefuck) wil gebruiken? Dan zit je met allemaal html-escaped zooi in je DB. Dat moet je nooit doen. Escaping regel je altijd aan de output kant.
Dank je! Heb ik voor de goede orde gecorrigeerd.
Verder snap ik je foreach niet... je voert nu 3x de query uit? Why :?
Ik denk ook dat de oorzaak van het probleem op dat stukje ligt, maar ik krijg het niet zelf opgelost.
Edit: na je post hieronder check ik dan toch de post nog even. Het form opent echter met:

code:
1
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">


...met daaronder direct het script uit de TS.

[ Voor 14% gewijzigd door Bastiaan op 29-08-2020 11:50 ]


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

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Bastiaan schreef op zaterdag 29 augustus 2020 @ 11:45:
[...]

Yes, dat weet het form. Op andere plekken in de testomgeving worden velden op dezelfde manier trouwens wel succesvol weggeschreven, dus de post-config zou oké moeten zijn, maar dat zijn dan ook allemaal velden met unieke namen.
Als alle velden in je adresbalk komen staan dan wordt er een GET uitgevoerd en geen POST. Basta. Dus dan zit daar iets mis.
Bastiaan schreef op zaterdag 29 augustus 2020 @ 11:45:
Dank je! Heb ik voor de goede orde gecorrigeerd.
Heb je mijn edit m.b.t. je foreach ook gezien?

[ Voor 18% gewijzigd door RobIII op 29-08-2020 11:46 ]

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

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Bastiaan
  • Registratie: November 2002
  • Laatst online: 12:39

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
RobIII schreef op zaterdag 29 augustus 2020 @ 11:45:
[...]

Heb je mijn edit m.b.t. je foreach ook gezien?
Gelijktijdig met jouw edit, blijkbaar :) En hoewel ik dan ga kijken hoe dan zeker de juiste werkwijze is ben ik inmiddels door je overtuigd dat dat nu niet de echte oorzaak van het probleem is.

Ik heb inmiddels de 'action=' losgetrokken van het document en verplaatst naar een los document. En inderdaad: ondanks dat er een post zou moeten plaatsvinden wordt die action-pagina niet eens opgeroepen. Zelfs als ik op die pagina alleen een refresh naar een externe website plaats blijf ik na het klikken op de update-button naar mijn tabel kijken en worden de waarden in de adresbalk gezet. Geen refresh naar Google dus, waar dat volgens de configuratie nu wel zou moeten, en dús wordt de juiste actie niet aangeroepen.

Acties:
  • 0 Henk 'm!

  • Bastiaan
  • Registratie: November 2002
  • Laatst online: 12:39

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Ik heb het hele form maar gedumpt en ben weer vooraan begonnen met opbouwen. Nu werkt het aanroepen wél, dus ik vermoed dat er toch ergens een tag of config verkeerd heeft gestaan.

Nu is het weer uitzoeken hoe deze query goed opgebouwd moet worden. Daar kom ik denk ik wel uit, aangezien ik nu zeker weet dat de resultaten van het testen zichtbaar zijn.

@RobIII, je zou me wel helpen met toelichten waarom in die setting de query driemaal wordt uitgevoerd. Voor zover ik nu weet hoort de query zelf buiten de foreach te staan en het preparen/uitvoeren daarbinnen, dus is het toch logisch dat deze steeds opnieuw moet worden aangeroepen om de regels/id's weg te schrijven?

Acties:
  • +1 Henk 'm!

  • Montaner
  • Registratie: Januari 2005
  • Laatst online: 01-09 08:19
Post de HTML van je formulier dan. Want POST in de method van een form zetten is niet echt rocket science...
Bastiaan schreef op zaterdag 29 augustus 2020 @ 13:06:
...
@RobIII, je zou me wel helpen met toelichten waarom in die setting de query driemaal wordt uitgevoerd. Voor zover ik nu weet hoort de query zelf buiten de foreach te staan en het preparen/uitvoeren daarbinnen, dus is het toch logisch dat deze steeds opnieuw moet worden aangeroepen om de regels/id's weg te schrijven?
code:
1
2
3
4
foreach ($data as $key => $value) {
  $stmt = $pdo->prepare($sql);
  $stmt->execute($data);
}

Hij wordt 3x uitgevoerd omdat je execute (uitvoeren) in je foreach staat. Oftewel, voor ieder stukje data voer de gehele sql uit. De hele foreach is overbodig. Zie:
https://www.php.net/manual/en/pdo.prepare.php
https://www.php.net/manual/en/pdostatement.execute.php

[ Voor 83% gewijzigd door Montaner op 29-08-2020 13:36 ]


Acties:
  • 0 Henk 'm!

  • Bastiaan
  • Registratie: November 2002
  • Laatst online: 12:39

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Montaner schreef op zaterdag 29 augustus 2020 @ 13:14:
Post de HTML van je formulier dan. Want POST in de method van een form zetten is niet echt rocket science...
Nou, inderdaad hè. Dat stond er ook, staat er nu weer, en na het opnieuw opbouwen de rest van het hele form wordt het aanroepen van de actions ook gedaan zoals het hoort.
Er stond dus elders in de code iets niet goed, maar dan zou ik straks in de versioning moeten gaan zoeken en vergelijken wat het precies was.
Hij wordt 3x uitgevoerd omdat je execute (uitvoeren) in je foreach staat. Oftewel, voor ieder stukje data voer de gehele sql uit. De hele foreach is overbodig. Zie:
https://www.php.net/manual/en/pdo.prepare.php
https://www.php.net/manual/en/pdostatement.execute.php
Ah, dank je! Er wordt dus geen onderscheid gemaakt tussen de query zelf of de execute. Beiden horen daar dus buiten te staan.

[ Voor 28% gewijzigd door Bastiaan op 29-08-2020 13:54 ]


Acties:
  • +1 Henk 'm!

  • Bastiaan
  • Registratie: November 2002
  • Laatst online: 12:39

Bastiaan

Bas·ti·aan (de, m)

Topicstarter
Bastiaan schreef op zaterdag 29 augustus 2020 @ 13:26:
[...]
Er stond dus elders in de code iets niet goed, maar dan zou ik straks in de versioning moeten gaan zoeken en vergelijken wat het precies was.
En gevonden. Ik heb de oude code teruggehaald en wilde direct naar het form zoeken/springen. Als resultaat op de zoekterm "<form" kreeg ik vervolgens twee hits. Twee? Ja dus. Op een totaal onlogische plaats stond nog een (lege) form-tag, zo'n 50 regels boven het eigenlijke form en daarom nooit eerder opgevallen.
Waarmee ik werkte bleek dus een genest formulier te zijn. Die verloren tag is ook zeker de oorzaak geweest van het niet werken van de post-method, aangezien ik het probleem van posten kan reproduceren door die tag te verwijderen of opnieuw toe te voegen.
Pagina: 1