Checkbox update meerdere tabellen MySQL, Ajax en PHP
Waar ik mee zit is het volgende:
Gebruikers kunnen data invoeren, dit d.m.v. tekst en checkboxes.
Deze dat word opgeslagen met een AJAX call naar het PHP script die via een MySQL query de data opslaat.
Deze data word in 2 tabellen opgeslagen. De tekst data in tabel products en de checkboxes in de koppeltabel productrel.
De koppeltabel gebruik ik voor de categorieën te koppelen met de tabel cats.
Onderstaand een simpele uitleg van de structuur.
Code (php)
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
28
29
30
31
32
33
34
35
36
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
28
29
30
31
32
33
34
35
36
Producten
+---+------------+
|ID | NAAM |
+---+------------+
| 1 |Kookboek |
+---+------------+
| 2 |Lotion |
+---+------------+
| 3 |Rijles theorie|
+---+------------+
Cats
+---+----------+
|ID | NAAM |
+---+----------+
| 1 |Speelgoed|
+---+----------+
| 2 |Body |
+---+----------+
| 3 |Boeken |
+---+----------+
| 4 |Verzorging|
+---+----------+
productrel
+---+----+
|PID | CID|
+---+----+
| 1 | 3 |
+---+----+
| 2 | 2 |
+---+----+
| 3 | 1 |
+---+----+
| 2 | 4 |
+---+----+
+---+------------+
|ID | NAAM |
+---+------------+
| 1 |Kookboek |
+---+------------+
| 2 |Lotion |
+---+------------+
| 3 |Rijles theorie|
+---+------------+
Cats
+---+----------+
|ID | NAAM |
+---+----------+
| 1 |Speelgoed|
+---+----------+
| 2 |Body |
+---+----------+
| 3 |Boeken |
+---+----------+
| 4 |Verzorging|
+---+----------+
productrel
+---+----+
|PID | CID|
+---+----+
| 1 | 3 |
+---+----+
| 2 | 2 |
+---+----+
| 3 | 1 |
+---+----+
| 2 | 4 |
+---+----+
Waar loop ik vast?
Als er een wijziging moet plaatst vind, moet de data worden ge-update worden.
Hiervoor maak ik gebruik van JSON zodat JavaScript de inputs vult.
Hoe kan ik dit het beste doen voor de checkboxes?
Zelf dacht ik aan een array terug te sturen en JavaScript de checkboxes als checked te markeren.
Daarnaast moet de koppeltabel ook ge-update worden.
Word er een checkbox unchecked dan moet deze ook van de koppeltabel verwijderd worden maar ook als in de wijziging van het product er een ander checkbox word aangevinkt dan moet deze in de koppeltabel juist ingevoerd worden.
Kan iemand mij hierbij helpen?
Quote:
Daarnaast moet de koppeltabel ook ge-update worden.
Word er een checkbox unchecked dan moet deze ook van de koppeltabel verwijderd worden maar ook als in de wijziging van het product er een ander checkbox word aangevinkt dan moet deze in de koppeltabel juist ingevoerd worden.
Word er een checkbox unchecked dan moet deze ook van de koppeltabel verwijderd worden maar ook als in de wijziging van het product er een ander checkbox word aangevinkt dan moet deze in de koppeltabel juist ingevoerd worden.
De makkelijkste manier is de geassocieerde records weggooien en opnieuw vullen. Daarbij is het ook zaak dat dit in één handeling gebeurt zodat je administratie blijft kloppen. Ik hoop dat je voor InnoDB-tabellen hebt gekozen zodat je database-transacties kunt gebruiken, want die worden op het moment dat je dit soort dingen wilt gaan doen noodzakelijk.
Stel namelijk dat je geen transacties gebruikt, en er halverwege zo'n bijwerk-actie iets misgaat. Dan is er mogelijk sprake van half verbroken/half gemaakte relaties tussen records en klopt je administratie niet meer. Een database-transactie garandeert dat zo'n batch van wijzigingen in zijn geheel of in zijn geheel niet wordt uitgevoerd.
Als je een administratief systeem hebt met dito database dan is InnoDB eigenlijk de gedoodverfde keuze. Daarbij is het ook zaak dat je grote zorg besteed aan het database-ontwerp.
Bedankt voor je reactie!
Het betreft inderdaad een administratief systeem, ik maak gebruik van AJAX omdat de databaes extern geladen word.
Er word inderdaad gebruik gemaakt van de InnoDB engine.
Dus je zegt eigenlijk in een handeling de rijen verwijderen via bijvoorbeeld het ID en dan een nieuwe record ervan maken?
In de koppeltabel uiteraard :p.
En als je categorie-relatie een ON DELETE CASCADE heeft in deze koppeltabel worden de records meteen opgeschoond als er een categorie wordt verwijderd uit de categorie-tabel. Foreign key relaties kunnen het op orde houden van de database verder vergemakkelijken.
Dus concreet ongeveer het volgende (aangenomen dat je de data van product X aan het wijzigen bent):
Code (php)
1
2
3
4
5
2
3
4
5
start transactie
werk data van product X bij
verwijder records van product X uit koppeltabel(len)
vul koppeltabel(len) opnieuw met relaties met product X
commit transactie
werk data van product X bij
verwijder records van product X uit koppeltabel(len)
vul koppeltabel(len) opnieuw met relaties met product X
commit transactie
Gewijzigd op 22/01/2020 01:04:05 door Thomas van den Heuvel
Bedoel je zoiets
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$mysqli = new mysqli("$hostdb", "$userdb", "passworddb", "db");
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$mysqli->begin_transaction();
$mysqli->query("UPDATE products SET productname='$productname' WHERE id=$id");
$mysqli->query("DELETE FROM relation WHERE PID=$id");
foreach($categorieids as $categoryid){
$mysqli->query("INSERT INTO relation (PID, CID) VALUES ('$productid', '$categoryid')");
}
$mysqli->commit();
$mysqli->close();
?>
$mysqli = new mysqli("$hostdb", "$userdb", "passworddb", "db");
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$mysqli->begin_transaction();
$mysqli->query("UPDATE products SET productname='$productname' WHERE id=$id");
$mysqli->query("DELETE FROM relation WHERE PID=$id");
foreach($categorieids as $categoryid){
$mysqli->query("INSERT INTO relation (PID, CID) VALUES ('$productid', '$categoryid')");
}
$mysqli->commit();
$mysqli->close();
?>
Enige kanttekeningen:
Vergeet niet een character encoding te selecteren na het maken van een connectie (met set_charset()) en escape alle data in je queries m.b.v. quotes + real_escape_string(). Dit om (later) problemen met input en output te voorkomen (invoer die quotes of non-ASCII karakters bevat).
Het loont misschien de moeite om een (kleine) wrapper te schrijven rondom de mysqli-class zodat je hier wat sneller/makkelijker mee kunt werken. Deze eenmalige investering ver*dient zich snel terug.
Gewijzigd op 24/01/2020 19:37:37 door Thomas van den Heuvel
Bedoel je dat ik classes maak zoals onderstaande gevonden op het internet
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
public function update($args)
{
$this->type = 'update';
$this->setTable($args['table']);
$query = $this->genQuery($args);
$stmt = $this->mySqli->prepare($query);
if ($this->mySqli->errno) {
die('Unable to insert data:<br /> '.$this->mySqli->errno .' : '. $this->mySqli->error);
}
$this->bindPar($args);
call_user_func_array(array($stmt, 'bind_param'), $this->returnRef($this->bind_arr));
if (!$stmt->execute()) {
die('Error : ('. $this->mySqli->errno .') '. $this->mySqli->error);
}
$stmt->close();
$this->reset();
}
?>
public function update($args)
{
$this->type = 'update';
$this->setTable($args['table']);
$query = $this->genQuery($args);
$stmt = $this->mySqli->prepare($query);
if ($this->mySqli->errno) {
die('Unable to insert data:<br /> '.$this->mySqli->errno .' : '. $this->mySqli->error);
}
$this->bindPar($args);
call_user_func_array(array($stmt, 'bind_param'), $this->returnRef($this->bind_arr));
if (!$stmt->execute()) {
die('Error : ('. $this->mySqli->errno .') '. $this->mySqli->error);
}
$stmt->close();
$this->reset();
}
?>
En vervolgens is deze overal aan te roepen met
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$args = [
'table' => 't1',
'data' => [
'f1' => 'test',
],
'where' => [
'id' => 10,
],
'and' => [
'f2' => 'foo',
]
];
$db->update($args);
?>
$args = [
'table' => 't1',
'data' => [
'f1' => 'test',
],
'where' => [
'id' => 10,
],
'and' => [
'f2' => 'foo',
]
];
$db->update($args);
?>
Gewijzigd op 24/01/2020 12:51:39 door Stefan Janssen
Maar op zo een moment ben ik persoonlijk van mening dat je een afweging tussen kosten, tijd en baten moet maken of het zinvol is. De MySQLi-functies zullen voorlopig niet worden aangepast, en als het zo zou zijn, dan is een algehele check-up van je code vast ook zeker nodig omdat er in een major versie vast nog meer dingen aangepast zullen worden. Doe gewoon wat jij het fijnst vindt werken. :-)
Voor een grote applicatie zie ik het nut er wel van in, hoewel je dan eigenlijk al aan een framework zoals Symfony of Laravel denkt die dit al aan boord heeft. Maar voor een kleine site vind ik het tijdsverspilling, tenzij je het leuk vindt ;-)
Wel kan je met de OO-variant je de standaard MySQLi-class uitbouwen. Zo kan je bijvoorbeeld je query functie opnieuw opbouwen, maar dan met 'exceptions' erin, of een teller bijhouden die je queries telt.
Gewijzigd op 24/01/2020 17:01:47 door - Ariën -
Quote:
De MySQLi-functies zullen voorlopig niet worden aangepast, en als het zo zou zijn, dan is een algehele check-up van je code vast ook zeker nodig omdat er in een major versie vast nog meer dingen aangepast zullen worden. Doe gewoon wat jij het fijnst vindt werken. :-)
...
Wel kan je met de OO-variant je de standaard MySQLi-class uitbouwen. Zo kan je bijvoorbeeld je query functie opnieuw opbouwen, maar dan met 'exceptions' erin, of een teller bijhouden die je queries telt.
...
Wel kan je met de OO-variant je de standaard MySQLi-class uitbouwen. Zo kan je bijvoorbeeld je query functie opnieuw opbouwen, maar dan met 'exceptions' erin, of een teller bijhouden die je queries telt.
Uh, spreek je hier jezelf niet een beetje tegen? En dat is toch een wrapper die je dan aan het schrijven bent?
Natuurlijk moet de wrapperfunctionaliteit je werk uit handen nemen, liefst zodat je met minder code hetzelfde/meer kunt doen.
Maar om terug te komen op het eerste fragment van bovenstaande quote: daar beschrijf je precies waarom een wrapper handig kan zijn: het ontkoppelt je code van een "hard coded" implementatie. Stel dat je overal real_escape_string() gebruikt, maar dat dat om een of andere reden (inhoudelijk) verandert (bijvoorbeeld dat je deze met extra of andere parameters moet aanroepen omdat er een default is veranderd). Dan zul je alle instanties van die aanroep overal in je code moeten opzoeken en moeten aanpassen (en daarmee propageer je in wezen het probleem van hard coding).
Had je daarintegen een (wrapper)methode gebruikt:
Code (php)
Dan hoe je enkel de desbetreffende regel code aan te passen en werkt vervolgens alle code die escape() gebruikt op de nieuwe manier.
Door deze ontkoppeling wordt het ook een stuk makkelijker om ondertussen te knutselen aan je wrapper-class, zonder dingen te breken in bestaande code, zolang je backwards compatible werkt, uiteraard.
En zoals @Ariën aangeeft kun je deze wrapper ook uitbouwen met extra functionaliteit zoals het (tijdelijk) loggen van queries, het tellen ervan, bijhouden of er al een transactie loopt et cetera.
EDIT: dus enkel al vanuit oogpunt van het verminderen van hard coding is er iets voor te zeggen om niet rechtstreeks de mysqli-functionaliteit te gebruiken.
Gewijzigd op 24/01/2020 19:53:49 door Thomas van den Heuvel
Op sich maakt een wrapper het wel makkelijker, maar het blijft in mijn ogen een kosten-baten analyze.
En tja, alles aanpassen kan prima met een fatsoenlijke editor. 'Replace and edit' en eventueel met een tussentijdse check. Als je toch naar een nieuwe PHP-versie gaat waar een functie wordt aangepast kan dat zeker geen kwaad. Hoe vaak verandert een MySQLi-functie opeens volgens jouw?
Ik zie het nut er zelf niet echt van in. Behalve in het uitbouwen, maar dat zie ik niet als een globale wrapper.
Voor wie het leuk vindt, ga je gang... ;-)
Gewijzigd op 24/01/2020 20:12:07 door - Ariën -
string functies, rekenkundige functies en uploadfuncties zijn appels, peren en ander fruit wat je met elkaar vergelijkt. Als je functionaliteit kunt groeperen in een of een aantal klasses, zoals uploadfunctionaliteit, dan loont dat de moeite. Je koppelt daarmee de functionele acties los van de technische implementatie, of liever gezegd, je refereert hier op een indirect manier aan. Dit is ook een stukje "defensief programmeren".
En voor de rest, ooit gehoord van helper classes? Daarin hercombineer je standaard functies voor een specifiek gebruik die je vaker toepast. Dat zijn in feite ook "wrappers".
Binnen een uur kun je een mysql wrapper in elkaar draaien die je in de toekomst werk uit handen neemt, dus probeer het eens uit zou ik zeggen. Of kijk eens in het rond voor inspiratie, en gebruik de delen die jou nuttig lijken.
Quote:
Ik zie het nut er zelf niet echt van in.
Wat niet is kan mogelijk nog komen.
Geen idee wat je bedoelt met globale wrapper.
Maar om een uur te frotten aan iets wat de meeste gangbare functies wrapt, en waar je later hoogstwaarschijnlijk niets mee doet.
Het maakt mij in ieder geval niet warm.
Helperclasses ken ik wel, maar die zitten al in diverse frameworks die al kant en klare functies hebben. Dan hoef je ook geen wrapper meer te bouwen.
That's my opinion. ;-)
Verder is dit ook niet bepaald de scope van dit topic.
Gewijzigd op 24/01/2020 23:57:48 door - Ariën -