pdo execute
Aan de PDO execute functie kun je een array $input_parameters meegeven, bijv.
Ik vind dit wel een prettige manier. Je kan ook gebruik maken van bindParam() maar dan moet je telkens aangeven wat voor type variabele het is (bijv. een string of een int). Het meegeven van een array aan de execute functie vind ik prettiger werken.
Nu wordt er op php.net over deze array gezegd:
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
Het gaat mij om het dikgedrukte stukje. Alle values worden als strings beschouwd. Echter, ik wil ook een getal kunnen ingeven (bijv. voor een id). Ik heb het even getest en dat lijkt gewoon goed te werken. Toch vind ik het raar dat die opmerking over die strings er dan bij staat vermeld. Heeft iemand een idee waarom die opmerking erbij staat, en kan dit op de een of andere manier voor problemen zorgen als ik een getal wil gebruiken?
Ozzie PHP op 08/05/2013 03:33:50:
Je kan ook gebruik maken van bindParam() maar dan moet je telkens aangeven wat voor type variabele het is (bijv. een string of een int).
In bindparam kan je aangeven wat voor type het is. Dat is het voordeel van bindparam. Als je het in execute meegeeft kan je dat niet en DUS moet alles op een identieke wijze worden verwerkt. De database engine kan niet ruiken wanneer jij een string bedoelt en wanneer jij een integer bedoelt. Alles is dus automatisch een string.
Wil je specifiek een integer invoeren, dan gebruik je dus bindparam.
Of het voor problemen kan zorgen durf ik niet 100% te zeggen. In principe niet denk ik, aangezien je een waarde altijd binnen quotes kan meegeven in een query. Niet nodig en in veel gevallen ook overbodig, maar het kan wel. Geef je een integer mee binnen quotes dan krijg je er niet eens een warning voor.
Toevoeging op 08/05/2013 10:52:00:
Edit:
De situatie waar je normaal geproken wilt dat een integer bijvoorbeeld NIET tussen quotes staat is voor het voorkomen van sql-injectie. Als je een int waarde zonder quotes geeft en het is een echte int dan gaat je query goed. Geef je het zonder quotes mee en staat er iets anders in, dan krijg je een error uit je database, query wordt niet uitgevoerd. Geef je echter een int tussen quotes op en staat er dan iets vreemds in, dan kan het wel uitgevoerd worden!
Echter, deze situatie is in jouw geval niet van toepassing omdat je een prepared statement gebruikt.
Bij int en string maakt het niet heel veel uit. Maar types al bool of null maakt dit wel uit.
Wouter J op 08/05/2013 11:34:42:
Bij int en string maakt het niet heel veel uit. Maar types al bool of null maakt dit wel uit.
In welke situatie zou dit voor problemen kunnen zorgen? Kan iemand een voorbeeld geven?
Bij MySQL maakt het inderdaad niet uit, bij SQL Server wel, daar krijg je een foutmelding als je een numeriek datatype quote. MySQL kent (net als de SQL standaard) overigens geen boolean datatype.
Maar is het dan "fout" om een numeriek datatype te quoten?
Hoe dan ook, is de manier waarop ik het nu doe 100% veilig? Ik maak dus gebruik van prepared statements, en ik geef de parameters als array mee in de execute() method. Of zeggen jullie dat ik toch beter bindParam() kan gebruiken? Is er een wezenlijk verschil?
Ozzie PHP op 08/05/2013 13:08:16:
Maar is het dan "fout" om een numeriek datatype te quoten?
Nee fout is het niet, ik vind het alleen niet in overeenstemming met de gedachte van portabilty achter PDO.
Dus als ik al prepared statements zou gebruiken (wat ik zeer zelden doe) dan zou ik met bindParam werken.
(Ik zou bijv. ook een functie kunnen maken waarbij ik een array meegeef en dat ik dan per key/value paar kijk welk datatype de value is, en afhankelijk daarvan bindParam aanroep met het juiste datatype. Maar wellicht is dit nogal over de top.)
Gewijzigd op 08/05/2013 13:31:48 door Ozzie PHP
Nee met Mysql dus niet. In ieder geval geen foutmelding op de query, en mocht er al performance verlies zijn dan is dat te verwaarlozen.
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
<?php
$foo = 'een string';
$bar = 10;
$array = array(':foo' => $foo, ':bar' => $bar);
// en dat je deze array dan omzet naar:
bindParam(':foo', $foo, PDO::PARAM_STR);
bindParam(':bar', $bar, PDO::PARAM_INT);
?>
$foo = 'een string';
$bar = 10;
$array = array(':foo' => $foo, ':bar' => $bar);
// en dat je deze array dan omzet naar:
bindParam(':foo', $foo, PDO::PARAM_STR);
bindParam(':bar', $bar, PDO::PARAM_INT);
?>
Zou dat enige toegevoegde waarde hebben? Of is het dan toch beter om gewoon een array zonder datatypes mee te geven aan execute()?
Gewijzigd op 08/05/2013 13:47:19 door Ozzie PHP
Ik loop nog steeds met het idee rond om een 'eigen' parameter methode te ontwikkelen, met als voorbeeld de bind methode van .NET. Daar kan je alle datatypes aan een parameter toewijzen, en owee als je dan een string aan een int parameter meegeeft.
Toevoeging op 08/05/2013 14:32:28:
Toch een probleem als je alleen de execute array gebruikt.
Als je bijv. "... LIMIT :limit_amount" wil doen dan mogen daar geen quotes omheen staan. De query zal dan mislukken.
Dus je wilt een id als int opslaan, dan ook altijd netjes $iId = (int) 1 ;
Je komt pas in de problemen als je applicaties groeien en daarmee de kans op slordigheidjes vergroot, dus per ongeluk toch een numerieke string voor id in de database plempen.
Zie mijn opmerking hierboven... als ik een LIMIT wil meegeven en ik dat via de array doe, dan wordt er een string van gemaakt en gaat het fout want dat mag niet in MySQL :(
Wat heeft het voor zin een parameter aan een LIMIT te geven?
Bijv. om in te stellen hoeveel rijen je wilt terugkrijgen?
Maar prepared statements zijn hoofdzakelijk bedoeld om je performance te verbeteren als je meerdere dezelfde query's achter elkaar uit moet voeren met verschillende waarden in de parameters.
Maar bij één enkele levert het performance verlies op (dat vind vooral jij niet zo leuk).
Gewijzigd op 08/05/2013 16:18:04 door Ger van Steenderen
Omdat ie dan ge-escaped wordt enzo? Dus veilig? Maar "limit" kan toch ook gewoon een parameter zijn? Of zie ik dat verkeerd?
"Maar prepared statements zijn hoofdzakelijk bedoeld om je performance te verbeteren als je meerdere dezelfde query's achter elkaar uit moet voeren met verschillende waarden in de parameters."
Is het echt meetbaar trager dan? Ik begreep juist dat het veiliger is om prepared statements te gebruiken ivm sql injection. Dus vandaar leek het me eigenlijk wel oké. Zit ik ernaast?
pdo.quote gebruikt, dan kan dat ook niet.
Maar bij een limit kan het eigenlijk ook al niet. Zoals jezelf eerder al aangaf kan je bij een limit geen quotes om de waarde heenzetten. Dus deze query gaat niet werken:
Daarnaast kan je geen twee queries in 1 keer uitvoeren, dus dit kan ook niet:
Ergo: via die limit clause kan je helemaal geen sql injectie krijgen. Ook geen noodzaak dus om daar prepared statements te gebruiken.
Veiliger dan wat? Ja, met prepared statements kan je geen sql injectie meer krijgen. Maar als jij je input goed controleert en bijvoorbeeld Maar bij een limit kan het eigenlijk ook al niet. Zoals jezelf eerder al aangaf kan je bij een limit geen quotes om de waarde heenzetten. Dus deze query gaat niet werken:
Daarnaast kan je geen twee queries in 1 keer uitvoeren, dus dit kan ook niet:
Ergo: via die limit clause kan je helemaal geen sql injectie krijgen. Ook geen noodzaak dus om daar prepared statements te gebruiken.
Daarnaast vind ik het wel duidelijker om prepared statements te gebruiken omdat je dan niet al je values hoeft te gaan quoten. Dat heeft ook wel weer z'n voordelen.
Maar ik zou graag weten waarom het niet oké is om prepared statements te gebruiken.