PHP en MySQL. Insert lukt niet.
Nu is het de bedoeling dat ik dat via een webpagina ga doen, zodat ik de data op een snelle(re) manier kan invoeren. Op termijn is het de bedoeling dat anderen ook toegang krijgen tot de pagina en hiermee dus ook de database kunnen vullen.
Ik heb hieronder een stuk tekst met daaronder de betreffende code geplaatst, met daaronder een nieuw stuk tekst en een nieuw stuk code, etc.
Ik heb hiervoor een script gebruikt via http://www.sitemasters.be/tutorials/2/1/78/MySQL/Formulier. Zie ook hieronder. Dit werkt prima.
Ik roep de php pagina db_config aan waarin mijn inloggegevens staan voor de (lokale) database.
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
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
<?php
require_once 'db_config.php'; //verbinding maken
mysql_select_db('rum') or die (mysql_error()); //errorhandling
if(isset($_POST['verzenden']))
{
$sVoornaam = addslashes($_POST['voornaam']);
$sAchternaam = addslashes($_POST['achternaam']);
$iLeeftijd = addslashes($_POST['leeftijd']);
mysql_query("INSERT INTO formulier (voornaam, achternaam, leeftijd) VALUES ('".$sVoornaam."', '".$sAchternaam."', '".$iLeeftijd."')") or die (mysql_error());
echo 'Je gegevens zijn succesvol in de database geplaatst';
}
else
{
?>
<form action=" <?=$_SERVER['PHP_SELF']?> " method="POST">
Voornaam: <input type="text" name="voornaam"><br />
Achternaam: <input type="text" name="achternaam"><br />
Leeftijd: <input type="text" name="leeftijd"><br />
<input type="submit" name="verzenden" value="verzenden">
</form>
<?
}
?>
require_once 'db_config.php'; //verbinding maken
mysql_select_db('rum') or die (mysql_error()); //errorhandling
if(isset($_POST['verzenden']))
{
$sVoornaam = addslashes($_POST['voornaam']);
$sAchternaam = addslashes($_POST['achternaam']);
$iLeeftijd = addslashes($_POST['leeftijd']);
mysql_query("INSERT INTO formulier (voornaam, achternaam, leeftijd) VALUES ('".$sVoornaam."', '".$sAchternaam."', '".$iLeeftijd."')") or die (mysql_error());
echo 'Je gegevens zijn succesvol in de database geplaatst';
}
else
{
?>
<form action=" <?=$_SERVER['PHP_SELF']?> " method="POST">
Voornaam: <input type="text" name="voornaam"><br />
Achternaam: <input type="text" name="achternaam"><br />
Leeftijd: <input type="text" name="leeftijd"><br />
<input type="submit" name="verzenden" value="verzenden">
</form>
<?
}
?>
Ik heb een aantal waarden aangepast en ik heb er onderstaand van gemaakt. Als ik dit uitvoer krijg ik mijn pagina met textboxen en een verzend knop weer terug, maar er worden geen records in de tabel `nose` weggeschreven.
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
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
<?php
require_once 'db_config.php'; //verbinding maken
mysql_select_db('rum') or die (mysql_error()); //errorhandling
if(isset($_POST['verzenden']))
{
$cRumName = addslashes($_POST['RumName']);
$iAge = addslashes($_POST['Age']);
mysql_query("INSERT INTO `nose` ('RumName', 'Age') VALUES ('".$cRumName."', '".$iAge."')") or die (mysql_error());
}
else
{
?>
<form action=" <?=$_SERVER['PHP_SELF']?> " method="POST">
Rumnaam: <input type="text" name="RumName"><br />
Leeftijd: <input type="text" name="Age"><br />
<input type="submit" name="Verzenden" value="Verzenden">
</form>
<?php
}
?>
require_once 'db_config.php'; //verbinding maken
mysql_select_db('rum') or die (mysql_error()); //errorhandling
if(isset($_POST['verzenden']))
{
$cRumName = addslashes($_POST['RumName']);
$iAge = addslashes($_POST['Age']);
mysql_query("INSERT INTO `nose` ('RumName', 'Age') VALUES ('".$cRumName."', '".$iAge."')") or die (mysql_error());
}
else
{
?>
<form action=" <?=$_SERVER['PHP_SELF']?> " method="POST">
Rumnaam: <input type="text" name="RumName"><br />
Leeftijd: <input type="text" name="Age"><br />
<input type="submit" name="Verzenden" value="Verzenden">
</form>
<?php
}
?>
Ik heb ook een query gemaakt in PHP die uit dezelfde tabel de waarden naam en leeftijd teruggeeft en in een tabel plaatst op de site. Dit gaat zonder problemen. (De code hiervoor staat hieronder).
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
require_once 'db_config.php'; //verbinding maken
mysql_select_db('rum') or die (mysql_error()); //errorhandling
$query = "SELECT `Age`,`RumName` FROM `nose` WHERE `Age` > '5' ";
//query is aangemaakt
$sql = mysql_query($query) or die ( mysql_error( ) );
//query is uitgevoerd
echo"<table>
<tr><td>Naam</td><td>Leeftijd</td></tr>";
while($record = mysql_fetch_object($sql)){
echo"<tr><td>".$record->RumName."</td><td>".$record->Age."</td></tr>";
}
echo"</table>";
?>
require_once 'db_config.php'; //verbinding maken
mysql_select_db('rum') or die (mysql_error()); //errorhandling
$query = "SELECT `Age`,`RumName` FROM `nose` WHERE `Age` > '5' ";
//query is aangemaakt
$sql = mysql_query($query) or die ( mysql_error( ) );
//query is uitgevoerd
echo"<table>
<tr><td>Naam</td><td>Leeftijd</td></tr>";
while($record = mysql_fetch_object($sql)){
echo"<tr><td>".$record->RumName."</td><td>".$record->Age."</td></tr>";
}
echo"</table>";
?>
Eerst dacht ik aan een rechten probleem, omdat ik wel kan lezen, maar niet kan schrijven. Ik heb daarom het gekopieerde script nog een keer in mijn PHP pagina gebruikt om te zien of ik de voornaam, achternaam en leeftijd in een andere tabel in dezelfde database wel weg kan schrijven. Dat lukte wel, dus ik denk dat het veilig is om de aanname te doen dat er voldoende rechten zijn.
Ik had eigenlijk gehoopt dat het gedeelte 'or die (mysql_error());' er voor zou zorgen dat ik een foutmelding zou zien, maar dat gebeurt ook niet. Ik heb dus nu geen idee wat ik fout doe en waar ik het nog moet zoeken.
Waarschijnlijk is het voor de toppers hier een peuleschilletje, dus als iemand me op weg zou willen helpen zou ik zeer dankbaar zijn.
- Ariën -:
Gelieve in het vervolg bij code de [code][/code]-tags gebruiken.
Hier kan je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Hier kan je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Gewijzigd op 01/11/2015 09:52:44 door - Ariën -
Verder is addslashes() geen beveiliging voor de database.
mysql_query("INSERT INTO nose (RumName, Age) VALUES ('".$cRumName."', '".$iAge."')") or die (mysql_error());
Ook dat heeft niet geholpen.
Ook de volgende variaties werkten niet:
mysql_query("INSERT INTO nose (RumName, Age) VALUES ('.$cRumName.', '.$iAge.')") or die (mysql_error());
mysql_query("INSERT INTO nose (RumName, Age) VALUES (".$cRumName.", ".$iAge.")") or die (mysql_error());
Verzenden" value="Verzenden">
if(isset($_POST['verzenden']))
Array indices zijn Case Sensitive.
Gebruik gewoon overal lowercase namen.
Ook is de volgende manier een betere om te kijken of er iets gesubmit is via POST:
<input type="submit" name="if(isset($_POST['verzenden']))
Array indices zijn Case Sensitive.
Gebruik gewoon overal lowercase namen.
Ook is de volgende manier een betere om te kijken of er iets gesubmit is via POST:
1) Je zet integer-waardes (zoals Age) tussen quotes. MySQL vindt het niet fout, maar het is altijd netter om getallen als getallen te behandelen en niet als strings. Hopelijk heb je Age gedefinieerd als een integer-type en niet als een (var)char, want dan kun je wel serieuze problemen verwachten.
2) De mysql-extensies gaan ergens in de toekomst vervallen. Als je dan niet je hele code wilt herschrijven, is het handig om nu alvast gebruik te maken van de mysqli-extensies of van PDO.
Een typecast middels (int) is uit den boze, omdat er in dat geval mogelijk getracht wordt invoer die helemaal geen getal bevatte om te zetten naar een getal. Vaak levert dat dan het cijfer nul op, of een andere, maar tevens onvoorspelbare, waarde.
Over drie jaar is iemand in jouw database nog net zo oud als nu...
Een paar keer per jaar komen we met vrienden bij elkaar om een rum en whiskey proeverij te houden. Iedereen neemt 1 of meerdere flessen mee en laat de overige deelnemers er van proeven.
Omdat we op de avond zelf alleen aan het genieten zijn en geen notities maken rees het plan om hiervoor een website op te zetten, zodat je kon kijken welke rum of whiskey de revue zijn gepasseerd en wat de verschillende smaken en stadia (geur, pallet en afdronk) zijn. Op die manier kun je ook gaan vergelijken op soorgelijke whiskeys of rums.
Dat is ook direct de reden dat ik de leeftijd opsla, omdat een rum of whiskey gebotteld wordt en op dat moment de leeftijd wordt meegegeven. Ook al bewaar je de fles daarna 100 jaar, de leeftijd is de leeftijd wanneer er gebotteld is.
Mochten er nog vragen zijn over dit project hoor ik het graag.
En de fouten waren inderdaad de "" en de hoofdlettergevoeligheid.
Iedereen bedankt voor de tips. Ik kan er weer verder mee en het is me inmiddels gelukt om een paar velden in MySQL te inserten via de php pagina.
Quotes geven in SQL alleen aan waar de data begint en eindigt, het heeft niets te maken met datatypen, dat komt pas wanneerde waarde wordt aangeboden aan de uiteindelijke kolom endie zal de *string* interpreteren om te zien of de inhoud past in het kolomformaat. Omdat quotes alleen de waarden afbakenen is het altijd beter om ze wel te gebruiken, dan om de queryparser te laten gokken over wat je bedoelt.
Als je waarden direct in een query plakt dan is het sowieso altijd verplicht om ze te quoten, want anders zet je je script open voor SQL injectie.
Dat is niet waar. Als je naar de BNF van SQL kijkt, zie je dat quotes alleen worden gebruikt voor string literals.
> het heeft niets te maken met datatypen, dat komt pas wanneer de waarde wordt
> aangeboden aan de uiteindelijke kolom en die zal de *string* interpreteren om
> te zien of de inhoud past in het kolomformaat. Omdat quotes alleen de waarden
> afbakenen is het altijd beter om ze wel te gebruiken, dan om de queryparser
> te laten gokken over wat je bedoelt.
Leuke theorie, maar hij slaat nergens op. ;-) De query parser voert een lexicale analyse uit op de query en zal dus een integer/decimal/etc zien als je geen quotes gebruikt, en een string als je wel quotes om de waarde zet. Dat wordt vervolgens vertaald in tokens die aan de SQL engine worden doorgegeven.
Als je quotes om een integer zet, zal de SQL engine dus een string aangeleverd krijgen in plaats van een integer. Vervolgens ziet de engine in de datadefinitie dat het een integerveld betreft, en zal hij de string naar een integer moeten typecasten. Overigens is dit qua performance verwaarloosbaar. Wat echter niet verwaarloosbaar is, is het gedrag van MySQL als je gequote integers gebruikt.
Wanneer je een insert doet op een enum-veld met numerieke waardes, moet je bijvoorbeeld goed opletten of je wel of geen quotes om je integer zet. Zonder quotes zal de waarde gezien worden als index van de enum, en met quotes wordt eerst gekeken of de enum een string bevat met die waarde. Zo niet, dan wordt het te inserten getal alsnog als index geïnterpreteerd. (Nu kun je je afvragen of het uberhaupt verstandig is je database op die manier in te richten, maar het gaat mij even om het voorbeeld dat je niet zomaar overal quotes omheen kunt zetten.)
Een ander leuk probleem dat je kunt tegenkomen is als je integerwaardes gebruikt die groter zijn dan de hardware van je systeem aankan. Die worden namelijk eerst gecast naar floating pointwaardes en pas daarna vergeleken. Het is echter mogelijk dat een integer op een andere manier wordt gecast dan een string (dat kan worden beïnvloed door bijvoorbeeld je hardware-architectuur of de versie/instellingen van de compiler) en omdat floats niet exact zijn, kan het dus voorkomen dat 'integer' <> integer.
De eerlijkheid gebiedt me te zeggen dat ik dit niet in de praktijk heb kunnen reproduceren, maar dit is wel zo'n probleem waar je rustig maanden naar kunt zoeken als je er last van hebt.
Iets wat je vaker in de praktijk zult tegenkomen, is het gebruik van een decimale komma in plaats van een decimale punt, omdat we dat nu eenmaal gewend zijn in Nederland. Stel dat je een waarde als 3,14 wilt inserten in een decimal/float-veld. Als je er quotes omheen zet, zal die waarde niet worden geconverteerd naar 3.14, maar naar 3.0. Zonder quotes krijg je een SQL-error en is het meteen duidelijk dat je input niet klopt. Dat heeft toch wel mijn voorkeur boven het inserten van verminkte data in een tabel.
> Als je waarden direct in een query plakt dan is het sowieso altijd verplicht
> om ze te quoten, want anders zet je je script open voor SQL injectie.
Ook als je waardes quote blijft je script openstaan voor SQL-injectie. Je kan immers ook quotes injecteren. ;-) De enige manier om je script te beveiligen is door alle input te sanitizen. En als het even kan prepared statements gebruiken, al moet ik zeggen dat ik dat in PHP nogal bewerkelijk vind...
En wat zou het mooi zijn als de topicstarter antwoordt met "k"... :D
@Pg Vincent
Quote:
Omdat quotes alleen de waarden afbakenen is het altijd beter om ze wel te gebruiken, dan om de queryparser te laten gokken over wat je bedoelt.
Als je waarden direct in een query plakt dan is het sowieso altijd verplicht om ze te quoten, want anders zet je je script open voor SQL injectie.
Als je waarden direct in een query plakt dan is het sowieso altijd verplicht om ze te quoten, want anders zet je je script open voor SQL injectie.
Ben ik het niet helemaal mee eens. Als je zorgt dat je je input filtert voor numerieke waarden zijn quotes (zelfs) helemaal niet nodig.
Het toevoegen van quotes alleen is ook niet genoeg, want magic_quotes_gpc() bestaat niet meer in nieuwere PHP-versies (dit biedt ook geen absolute garanties
Daarnaast mogen de DATA-delen in je query niet behandeld worden als SQL, daarvoor is de MySQL-context-specifieke escaping functie/methode real_escape_string().
Het toevoegen van real_escape_string() alleen (zonder quotes) is OOK niet genoeg omdat er niets ge-escaped wordt als er niets te escapen valt, bijvoorbeeld met ...OR 1=1.... Het komt nogal eens voor dat real_escape_string() als een soort toverformule gebruikt wordt (SIMSALABIM!) en dat na afloop (ten onrechte) verondersteld wordt dat alles veilig is (terwijl geen quotes om het geheel waren geplaatst).
Alleen de combinatie van beide middelen (het toevoegen van quotes en het escapen van de inhoud met de daarvoor bestemde functie/methode) is veilig, en dan alleen wanneer je character encoderingen kloppen. Als deze niet kloppen / uit de pas lopen kan niet gegarandeerd worden dat de escaping goed gaat. Daarom geeft een (andere) escaping functie als htmlspecialchars() ook een lege string terug als de encodering van de string-parameter niet overeenkomt met de opgegeven encodering, omdat er dan simpelweg niet gegarandeerd kan worden dat het resultaat "HTML safe" is.
@Willem vp
Quote:
De enige manier om je script te beveiligen is door alle input te sanitizen.
Als je met sanitizen bedoelt "repareren tot iets geldigs", ik zou het niet doen. Dat is toch net zoiets als typecasting. Als je bedoelt "filteren" dan ben ik akkoord. Als je input "niet past", gewoon weigeren.
Ik zie dit soort constructies te vaak:
Als $_GET['id'] vervolgens 'aap' bevat wordt dit getypecast naar het cijfer 0. Maar het heeft (mogelijk) totaal geen zin om zo'n query uit te voeren omdat deze of geen, of onvoorspelbare resultaten oplevert. Onvoorspelbaar, omdat er met een typecast een interpretatiestap wordt uitgevoerd, "Oh hij zal wel X of Y bedoeld hebben".
Als je met sanitizen bedoelt "repareren tot iets veiligs", dan ben ik het daar ook niet mee eens, wat je dan in feite doet is 'escape-on-input'. Ook dat lijkt mij een slecht idee.
Idealiter sla je "geldige" data (dit hoeft niet per sé "wenselijke" data te zijn, hier mogen nog best dingen in zitten die bij een later gebruik schade aan kunnen richten) rauw op, zodat je deze later weer makkelijk kunt bewerken. Als je deze bijvoorbeeld opslaat met htmlentities() ofzo (Joost mag weten waarom), dan zul je op een zeker moment weer de omgekeerde bewerking uit moeten voeren. Dit brengt ook weer allemaal problemen met zich mee en in zijn algemeenheid wordt je applicatie complexer door dit soort vertaalslagen.
Ik ben van mening dat je invoer exact moet kloppen nog voordat je een query of wat dan ook uitvoert. Wat als dit een kostbare operatie is? Het is een verspilling van resources. Filter input, klopt je invoer niet, pech (maar doe niets!).
Als iederen zich nou gewoon van het devies filter input, escape output zou bedienen (en tevens begrijpt wat dit inhoudt)...
Gewijzigd op 02/11/2015 16:50:27 door Thomas van den Heuvel
Eddy E op 01/11/2015 08:24:40:
Mooi stuk.
En wat zou het mooi zijn als de topicstarter antwoordt met "k"... :D
En wat zou het mooi zijn als de topicstarter antwoordt met "k"... :D
"k"...
En gaaf om te zien hoe een vraag in een beginnersforum zo'n geweldige discussie ontketent!