ik heb eens nagekeken en inderdad ging er iets mis bij invoer, bij mijn mainimage deel
ik heb deze er tijdelijk maar even uitgehaald nu werkt het wel weer
Even iets heel anders. Waarom maak je gebruik van prepared statements in mysqli? Dit is echt compleet ruk.
Daarnaast, je maakt hier wel een hele rare spagaat door de helft van je DATA gewoon te concateneren in je SQL-string.
Nu zou je zeggen "ja maar dat zijn opties die uit het systeem komen, en dus zijn ze veilig" ofzo. Dat klopt misschien wel, maar iedereen die ooit die code ziet zal zich daarvan moeten vergewissen. Je laat mensen dus onnodig nadenken over query-veiligheid, terwijl prepared statements hier juist voor bedoeld zijn!
En wat als je straks een twijfelgevalletje hebt: een waarde die van een externe bron afkomstig is, maar gevalideerd is en dus veilig is (en daarbij, hoe verschilt dat dan precies van de bovenstaande $this->options)? Neem je deze gewoon in de SQL op? Of toch via een parameter? Maar wat houdt dat dan in als je deze gewoon concateneert, maakt dit dan prepared statements niet helemaal overbodig als je alles gewoon fatsoenlijk vantevoren valideert?
Op dit moment zit er sowieso geen lijn in wat je doet. Ik zou je dringend aanraden om dit te fixen en hierbij gewoon af te stappen van prepared statements in MySQLi. Bij gebrek aan eigen inspiratie doe een van de twee dingen:
- stap over naar PDO en gebruik daar prepared statements (maar dan dus consequent op de goede manier)
- gebruik MySQLi en escape de DATA-delen met real_escape_string() in combinatie met quotes
En wat @Ivo dus zegt, je hebt een manier nodig om foutmeldingen met queries te detecteren en/of af te handelen. Je zou dus sowieso veel profijt hebben van een soort van database-wrapper. Je kunt op die manier veel sneller fouten (met queries) localiseren.
Nu ben je waarschijnlijk nog geen biet wijzer, want in wezen zeg je "het ging fout, en ik weet niet waarom, en nu gaat het weer goed, en ik weet nog steeds niet waarom". Het is jouw taak als programmeur om dit uit te zoeken om herhaling te voorkomen. Code besluit niet zomaar om op het ene moment wel te werken en het andere moment niet. Wat dat betreft is code heel makkelijk: het doet *precies* wat het is voorgeschreven om te doen.
ja meester :P
nee maar je hebt wel gelijk
die prepared statements saten al in het oorspronkelijke login script waar ik 10 jaar mee ben begonnen
voor mysqli gebruikte ik dit niet maar ik kon geen goede werkende manier vinden die voor all mijn paginas werkte en dus heb ik dit gebruikt
ik moet ook een keer het geheel op de schop gooien en nieuw maken
echter is dit niet zo makkelijk gedaan als gezegd
mijn script is om het even heel bot te zeggen jarenlange ideeen scripten en aanpassingen in een werkende bedrijfs omgeving
het zijn serieus misschien wel meer dan 2000 files
ik zou het op dit moment ook niet echt weten
hele boekhoudingen worden met mijn gehele systeem gedaan
POS systemen
verschillende dynamische websites die allemaal met elkaar samenwerken
het is misschien verouderde code maar het werkt en ik verbeter elke dag
en het meeste werkt perfect hoor maar het heeft zeker wel verbetering nodig of eigelijk
geheel nieuw
maar ik kan niet zomaar even een nieuwe maken omdat ik daarvoor een werkende omgeving nodig hebt
ik test veel voordat ik iets online zet maar als scripter kan je ook niet altijd alles voorzien
daar huur ik soms beta testers voor in omdat ik het zelf in mijn 1tje gewoon niet altijd alleen kan doen
bedoeling is dat ik over een jaar een geheel nieuw script ga maken
het bestaande script moet dan eerst helemaal zijn hoe ik het wil
en daarna ga ik het gehele script herschrijven met moderne code
waarschijnlijk moet ik dan een heel team inhuren
want het is echt heeeeeel veel werk
en het moet allemaal dus werken op de oude database zonder ook maar 1 foutje
1 foutje betekent direct faliet voor 10+ bedrijven
1 uur offline kan duizenden euros kosten
om die reden wacht ik dus nog even tot ik zeker weet dat alles perfect is in het oude systeem
en ik denk dat ik bijna zover ben maar soms maak ik snelle aanpassingen in niet noodzakelijke delen en dan krijg ik dus dit soort errors
ach het werkt allemaal weer gelukkig daar gaat het om
ik moet ook een keer het geheel op de schop gooien en nieuw maken
Mja, maar met een database-wrapper of als je dit met een uitgebreidere class nog verder uit code abstraheert is dat dus niet nodig. Je probleem op dit moment wordt grotendeels veroorzaakt door hard coding. Beschouw het INSERT-statement uit je oorspronkelijke bericht.
Voorheen gebruikte je waarschijnlijk:
mysql_query(...)
Toen schakelde je over op MySQLi:
mysqli_query(...)
En toen had je waarschijnlijk gehoord dat prepared statements de bom was en deed je dit:
NB: de naamgeving die jij gebruikt ($query) is niet echt fantastisch. prepare() retourneert een statement object of false. Geef variabelen zelfdocumenterende namen.
Anyhow, volgende keer is het waarschijnlijk weer een andere flavor of the month.
Wat je tot nu toe functioneel hebt gedaan is echter nooit veranderd: je INSERT nog steeds een record in een tabel. Dan je beklag dat er zoveel bestanden zouden zijn waarin je dit soort dingen zou moeten aanpassen. Sja, als je nooit nadenkt hoe je dit op een indirecte manier voor elkaar krijgt dan zul je dus inderdaad elke keer alle bestanden in moeten duiken om deze hard coded meuk aan te passen.
Maar wat nu als je eens gaat nadenken over hoe je dit wel op een indirecte manier regelt waarbij je dus hard coding vermijdt? Je zou bijvoorbeeld een soort van INSERT-methode kunnen maken voor je database/informatiedrager (wat deze ook moge zijn, dit abstraheer je uit je code). Het daadwerkelijk uitvoeren zit dan in de implementatie van deze code, en niet meer in de lopende code van deze "scripts".
Super simpel voorbeeld:
<?php
class MyDB {
protected $db;
public function __construct($options) {
$this->db = new mysqli(...); // use $options
$this->db->set_charset(...); // preferred charset
}
public function insert($table, $args) {
$sql = 'INSERT INTO '.$table.' (';
$sql .= implode(', ', array_keys($args));
$sql .= ') VALUES (';
$sql .= implode(', ', $this->quote($args));
$sql .= ')';
// echo '<pre>'.$sql.'</pre>';
$this->db->query($sql);
}
public function insertId() {
return $this->db->insert_id;
}
protected function quote($args, $escape=true) {
$out = array();
foreach ($args as $v) {
$out[] = "'".($escape ? $this->escape($v) : $v)."'";
}
return $out;
}
public function escape($arg) {
return $this->db->real_escape_string($arg);
}
}
?>
Als er nu iets in database-land verandert hoef je enkel de IMPLEMENTATIE van de insert() methode aan te passen, en hoef je echt helemaal 0,0 te veranderen in al die 2000 bestanden zelf.
Laat dit ff bezinken.
Ik denk dat hiermee al vrij duidelijk is dat het gebruik van een wrapper gigantische voordelen heeft ten opzichte van alles maar rauw in je code duwen...
Sylvester vader op 11/09/2019 19:28:15
ach het werkt allemaal weer gelukkig daar gaat het om
Simpelweg omdat iets werkt maakt het nog niet juist.
aaaaaaa hoofdpijnnnnnnn :P dit is nog chinees voor mij maar ik snap het wel
en inderdaad eerst gebruikte ik mysql_query(...)
echter toen had ik dus al die prepared ergens in het toen login script die ik toen had (wist toen nog niet eens dat dat kon op die manier
toen ik over moest naar mysqli_query(...)
kwam ik erachter dat ik er een db connectie bij moest doen en dit was vroeger met
mysql_query(...) niet nodig
echter omdat ik dus zoveel code had in heel veel paginas lukte het mij niet om dit op normale manier aan te passen doormiddel van een bulk edit
toen vond ik dus die manier van prepared en daarmee kon het wel
probleem is dus dat ik zelf alles moet leren en dus helaas nogsteeds niet alles kan
jij hebt mij nu dit geleerd met dat ene stukje en het klinkt eigenlijk heel simpel (weer iets geleerd) dus in nieuwe versie zal ik het inderdaad waarschijnlijk zo doen :)
dus bij deze bedankt voor de kleine maar wijze les
Nu zou je zeggen "ja maar dat zijn opties die uit het systeem komen, en dus zijn ze veilig" ofzo. Dat klopt misschien wel, maar iedereen die ooit die code ziet zal zich daarvan moeten vergewissen. Je laat mensen dus onnodig nadenken over query-veiligheid, terwijl prepared statements hier juist voor bedoeld zijn!
Ik heb nog wel een voorbeeldje waarom "de waarde komt uit het systeem en is dus veilig" niet opgaat:
Ik heb ooit een bug moeten vinden waarom 1 medewerker nooit een order kon afhandelen, terwijl de rest dat prima kon doen.
Uiteindelijk bleek, dat in de logging de naam van de medewerker geplaatst werd. Was mooier geweest als dat het gebruikers_id was geweest, maar a la.
Deze naam was "veilig" volgens bovenstaande redenatie, maar omdat meneer iets van D'Artagnan heette, ging de query grandioos mis.
ja lol heb ik ook ooit meegemaakt zoiets met een quote :P
altijd leuk in text delen in een script met een soort wysiwyg script
als je dan in de text een quote zette dan voerde hij dus de query niet uit :P
dat heb ik toen gelijk aangepast want dat hielt ook in dat er een inject mogelijk was
maar in het begin snapte ik er niks van :P
Een blacklist is nooit een goede oplossing. Als je een case mist ben je de sjaak.
echter omdat ik dus zoveel code had in heel veel paginas lukte het mij niet om dit op normale manier aan te passen doormiddel van een bulk edit
toen vond ik dus die manier van prepared en daarmee kon het wel
Ah, de aloude vertrouwde aardappelstempel. Als je dat op die manier moet doen, is dat vast niet de laatste keer dat je dat op die manier moet doen. Verander dus van aanpak.
"de waarde komt uit het systeem en is dus veilig"
Even voor de duidelijkheid: die redenatie klopt dus niet! Je mag er nooit vanuit gaan dat als DATA eenmaal in je systeem zit (die nog steeds afkomstig was van gebruikers) ineens veilig zou zijn. Je zult deze dus altijd zonder uitzondering als "onbetrouwbaar" moeten behandelen. Alle DATA zou dus altijd en overal ge-escaped moeten worden, tenzij je een (gedocumenteerde) reden hebt om dit niet te doen.
Dit werkt ook een stuk eenvoudiger: je hoeft niet langer na te denken of iets veilig is of niet (met bijbehorend gevalsonderscheid voor elke individuele case) als je het gewoon altijd als "onveilig" behandelt.