mysqli_stmt_bind_param / only variables should be passed by reference

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Jan R

Jan R

01/06/2020 11:11:22
Quote Anchor link
Hi,

Ik krijg een fout, zie titel, in mijn code

Dit is de inhoud van de velden
Quote:
Array
(
[0] => mysqli_stmt Object
(
[affected_rows] => 0
[insert_id] => 0
[num_rows] => 0
[param_count] => 14
[field_count] => 0
[errno] => 0
[error] =>
[error_list] => Array
(
)

[sqlstate] => 00000
[id] => 1
)

[1] => 2020-11-03
[2] => 5 ° heen ronde
[3] => abc
[4] => 0
[5] => #000000
[6] => #00ffff
[7] => 127.0.0.1
[8] => Jan-I9
[9] => Jan
[10] => 2020-06-01 11:05:36
[11] => 1
[12] => 2
[13] => 2020-05-11
[14] => 234
)

Dit is de code
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$sql
='update trn_volgenderondeinfo set datum=?, naam=?, opmerking=?, pinkinterval=?, forecolor=?, backcolor=?, ip=?, provider=?, user=?, changedate=?, showbyes=?, tonen=?, van=? where id=?';
$stmt=mysqli_prepare($con, $sql);

logtext('log.log', array($stmt, $d1, $naam, $opmerking, $pinkinterval, $forecolor, $backcolor, $changer_IP, getprovider(), $changer_user, $changer_date, $showbyes, $tonen, $d2, $id));

mysqli_stmt_bind_param($stmt, 'sssissssssiisi', $d1, $naam, $opmerking, $pinkinterval, $forecolor, $backcolor, $changer_IP, getprovider(), $changer_user, $changer_date, $showbyes, $tonen, $d2, $id);

$stmt->execute();
if ($stmt->errno) {
  //echo "Fout: " . $stmt->error;
  echo 'Fout: tijdens opslaan wijzigingen';
}

$stmt->close();
?>


Waarom die fout? Alle velden hebben een waarde, stmt lijkt me correct en de type verwijzing lijkt me ook ok.
De fout is op lijn 7 volgens deze code.
De query wordt wel uitgevoerd????

Jan
Gewijzigd op 01/06/2020 11:13:24 door Jan R
 
PHP hulp

PHP hulp

25/11/2024 21:29:25
 
Adoptive Solution

Adoptive Solution

01/06/2020 11:34:02
Quote Anchor link
De melding zegt dat alleen variabelen mogen worden doorgegeven.

getprovider() is geen variabele.

Misschien eerst dit doen :

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$getprovider = getprovider();
 
Jan R

Jan R

01/06/2020 11:45:01
Quote Anchor link
Hoe is het mogelijk. Daar zit ik dan zo lang op te kijken.
Bedankt voor het snelle antwoord.

Jan
 
Thomas van den Heuvel

Thomas van den Heuvel

01/06/2020 16:40:39
Quote Anchor link
Als je dan toch prepared statement functionaliteit wilt hebben, waarom gebruik je dan geen PDO? In MySQLi is dit onwijs omslachtig, het maakt je code zo ontzettend wollig of in ieder geval een stuk langer.

Ik denk dat de "prijs" die je moet betalen voor veilige queries (mits dit alles correct gebruikt wordt uiteraard) via deze methode te hoog is voor wat je hier allemaal voor moet doen. Vergelijk: prepare(), bind(), execute(), close() vs simpelweg query()?

EDIT: en als je dan dit kunstje een aantal keren hebt gedaan dan schrijf je een class of wrapper hiervoor ofzo? Don't Repeat Yourself.

Met enige discipline kun je in MySQLi queries ook veilig maken zonder prepared statements. In beide gevallen (zowel de prepared statement variant alsook de variant zonder) moet je nog steeds weten wat de queries veilig maakt, dus in dat opzicht maakt het echt niet uit welke vorm je gebruikt.

Overigens zijn prepared statements in MySQLi echt "native" MySQL prepared statements - er wordt dus echt eerst een querysjabloon naar de database gestuurd en als je de query uitvoert wordt dit sjabloon voorzien van waarden. Hierbij wordt een ander protocol gebruikt om met de database te communiceren (het zogenaamde binaire protocol geloof ik) wat alles wat efficiënter maakt, maar voor alle SELECT, UPDATE etc queries worden dus effectief twee queries uitgevoerd (een voor het sjabloon, een voor executie). Je zou je kunnen afvragen wat daar precies de meerwaarde van is als je elke sjabloon in veruit de meeste gevallen maar één keer "gebruikt" voor de uitvoering van een enkele query...

De prepared statement laag van PDO daarentegen maakt niet per definitie gebruik van deze native variant omdat niet alle databases waar via PDO mee gecommuniceerd kan worden deze functionaliteit zelf heeft. Via de MySQL-driver kun je dit toch instellen (als je dat zou willen, en als het databasetype dit ondersteunt) via PDO::ATTR_EMULATE_PREPARES (default true, zet op false voor native variant).

Ik ben er nog steeds niet echt over uit in welke scenario's prepared statements op databaseniveau echt meerwaarde hebben. Misschien bij een importscript ofzo waarbij je heel veel INSERTs doet in dezelfde tabellen. Maar volgens mij zijn de toepassingen waarbij dit stukje (potentieel) performancewinst echt gaat tellen op één hand te tellen.

Dus vraag je ook echt af waarom je voor deze aanpak kiest, en laat dit dus ook echt een bewuste keuze zijn, waarbij de motivatie toch echt wat verder moet gaan dan "ik had gehoord dat dit veilig was" :p.
Gewijzigd op 01/06/2020 16:46:11 door Thomas van den Heuvel
 
Jan R

Jan R

01/06/2020 18:31:38
Quote Anchor link
Thomas van den Heuvel op 01/06/2020 16:40:39:
"ik had gehoord dat dit veilig was" :p.


Dat is het geenszins :)
Ik ben begonnen met mysql. pdo begon pas en er was weinig of geen info. Dan overgestapt op mysqli. Een beetje van moeten maar ook omdat mysql verouderd was en ik probeer alles up-to-date te houden. Deze overstap was ook logisch omdat deze weinig verschil had met de oude mysql functies. Ik bouwde en nog steeds eigenlijk de query op van nul. Gewoon opletten of alle aanhalingstekens er staan en zeker mysqli_real_escape_string niet vergeten. Dit lukt me meestal héél goed maar nu wou ik eens kijken hoe preparestm werkte. Met toch wat gesukkel voor wat moet ik nu gebruiken of net niet.
ook deze info vond ik belangrijk
w3schools:
Prepared statements are very useful against SQL injections, because parameter values, which are transmitted later using a different protocol, need not be correctly escaped. If the original statement template is not derived from external input, SQL injection cannot occur.


Maar verder wat zou toekomst gericht beter zijn. Gewoon mysqli blijven gebruiken of overstappen naar pdo?
volgens https://www.w3schools.com/php/php_mysql_connect.asp is het gewoon een keuze. Info is misschien wel wat oud. Het staat er niet bij!

om niet steeds alle info te typen werk ik nu ook met een functie voor mijn connectie.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
    $con
=opendatabasei();
?>


Jan
 
Rob Doemaarwat

Rob Doemaarwat

01/06/2020 19:07:50
Quote Anchor link
Maar maak dan in ieder geval een wrapper. Dit ziet er niet (leesbaar) uit.

Het (doe het zelf) framework waar ik normaal mee werk kan ik gewoon een "DB object" uit de lucht trekken (een wrapper om PDO - geen gedoe met MySQL, MS-SQL, Oracle, enz). En pas als ik echt een query ga doen wordt er "on the fly" een connectie aangemaakt. En dan gaat het dus in de vorm van:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?php

$records
= $db->select('tabel','*',['a' => 5]); //select * from `tabel` where `a` = 5
$db->update('tabel',['x' => 2],['a' => 5]); //update `tabel` set `x` = 2 where `a` = 5
$records = $db->all('
  select * from `tabel` t
    join `ander` a on a.a = t.a
  where t.x in (:x)'
,
  [
'x' => [2,5,7]]
);


?>

Alles netjes ge-bind enz.
Gewijzigd op 01/06/2020 19:12:30 door Rob Doemaarwat
 
Thomas van den Heuvel

Thomas van den Heuvel

01/06/2020 22:34:51
Quote Anchor link
w3schools:
If the original statement template is not derived from external input, SQL injection cannot occur.

Mja, dat is een redelijk zelfdienend argument. Je zou hier net zo goed van kunnen maken:
Quote:
If all the external input is properly escaped SQL injection cannot occur.

Hier heb je echt geen prepared statements voor nodig. Echter, als je deze op de goede manier gebruikt doet dit stramien dit voor jou onder water.

Not everything on the internet is true.
- Abraham Lincoln
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.