PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Prepared Statement



Janiboy
14.06.2010, 15:34
Hallo Leute,

ich programmiere gerade ein Benutzergruppen-System mit PHP und MySQLi. Dazu verwende ich, um mich gut vor Angriffen schützen zu können, so genannte Prepared Statements.

Um einfach Berechtigungen hinzufügen zu können, habe ich alle Rechtenamen in einem Array gespeichert, wozu er mir dann ganz simpel ein Formular generiert.

Hier das Ganze einmal in gekürzter Version:

<?php
$perm_hash = array('perm_user');
foreach($perm as $perms)
{
$sql1.= ', '.$perms;
$sql2.= ', ?';
$sql3.= 'i';
$sql4.= ', '.((isset($_POST[$perms]) ? $_POST[$perms] : 0));
}
$query = $SQL->prepare('INSERT INTO `usergroup` (`group_name`, `group_description`'.$sql1.') VALUES (?, ?'.$sql2.')');
$query->bind_param('ss'.$sql3, $_POST['group_name'], $_POST['group_description'].$sql4);
$query->execute();
?>

Der Code ist zum Speichern zuständig, wo er mir dann folgenden Fehler auswirft:


Fatal error: Cannot pass parameter 3 by reference in C:\xampp\htdocs\test\usergroup.php on line 11

So, nun frage ich mich: Why?

Wenn ich anstatt $sql4 einfach $_POST['perm_user'] hinschreibe, funktioniert das super. Warum klappt es nur nicht in dem Teil direkt und wie kann ich das Problem beheben? Möchte ja nicht immer alle 100 Abfragen bearbeiten, nur weil ich mal ein Recht hinzufüge/entferne.

Ich bedanke mich im Voraus!

bayer
14.06.2010, 16:32
Hi Janni,

Ich versuche dir mal zu helfen :)

Meiner Meinung nach liegt das Problem in folgender Zeile:


$query->bind_param('ss'.$sql3, $_POST['group_name'], $_POST['group_description'].$sql4); Kleiner Blick in die PHP-Manual (http://php.net/manual/de/mysqli-stmt.bind-param.php) verrät uns:


The number of variables and length of string types must match the parameters in the statement. Das ist bei dir nicht der Fall ;) Deine Types sehen so aus: ssi (String, String, Integer)
Sind 3 an der Zahl, du übergibst aber nur 2 Variablen an das bind_param.

Die Funktion braucht einzeln übergebene Variablen. Concatenated Strings mag die nicht, und genau soeinen String baust du hier:


$sql4.= ', '.((isset($_POST[$perms]) ? $_POST[$perms] : 0)); Ergo:



<?php
$perm_hash = array('perm_user');
foreach($perm as $perms)
{
$sql1.= ', '.$perms;
$sql2.= ', ?';
$sql3.= 'i';
$sql4.= (isset($_POST[$perms]) ? $_POST[$perms] : 0);
}
$query = $SQL->prepare('INSERT INTO `usergroup` (`group_name`, `group_description`'.$sql1.') VALUES (?, ?'.$sql2.')');
$query->bind_param('ss'.$sql3, $_POST['group_name'], $_POST['group_description'], $sql4);
$query->execute();
?>
Sollte hinhauen ;)

Janiboy
14.06.2010, 17:28
Hey,

super, das funktioniert auch wunderbar. Problem jedoch ist, dass mein Array wächst und somit dann bei einem zweiten, dritten, vierten usw. Wert zu wenig Kommas hat. Wie kriege ich die Kommas denn dann dynamisch integriert in den Befehl? Vorher hatte ich die ja einfach in sql4 vorne mit beigepackt, was er aber nicht mag. Kriege ich das irgendwie noch hin?

Ich danke dir ganz herzlich!

bayer
14.06.2010, 18:20
Schön, dass das schonmal hinhaut ;)

Um dein weiteres Vorhaben zu bewerkstelligen, musst du einen, ich sag mal "unschönen Trick" anwenden ;)

Dieser Trick sieht so aus:




$params = array('ss', 'bla', 'Blubb');
// array(Types, Wert1, Wert2, usw...)
$tmp = array();
foreach($params as $key => $value) $tmp[$key] = &$params[$key];
call_user_func_array(array($stmt, 'bind_param'), $tmp);


Musst du halt noch auf deinen Code anpassen.

Hoffe, ich konnte dir nochmal helfen ;)

Janiboy
14.06.2010, 18:55
oh weia, da blicke ich nicht durch. :o

bayer
14.06.2010, 20:05
Bin grad noch mit meinem Studium beschäftigt. Drösel dir das später auf :)

Janiboy
14.06.2010, 20:07
Sehr nett. Ich probiere selbst noch ein wenig herum, vielleicht schaffe ich das ja noch. :)

Danke Dir!

bayer
14.06.2010, 22:31
Könnte bei mir doch etwas später werden, eventuell morgen.

So schwer is der Trick aber auch net zu verstehen ;)

Am besten wärs, wenn du mir deine ICQ-UIN per PM schickst, dann können wir das besser besprechen. Die Struktur deiner Tabelle wär ganz gut zu wissen :)

Kriegen wir schon hin :D

Janiboy
15.06.2010, 18:46
Habe im Moment kein ICQ installiert. Eilt aber auch nicht, da ich es erst mal ohne Prepared Statement provisorisch gelöst habe.

Die Tabellenstruktur ist ganz simpel:

group_id, group_name, group_description, <entsprechende Berechtigungen, wie z.B. perm_user, die haben dann entweder 0 für kein Zugriff oder eine 1 für erlaubt. Das wars dann schon. Die Berechtigungen fangen dann alle immer mit perm_ an und dann die entsprechende Sektion auf der Page.>

Aber wie gesagt, es eilt nicht. Danke dir ganz herzlich!