Hallo Bernd,
nein, den Begriff "Schleife" hatte ich anders gemeint. Ich verkürze deine Statements mal etwas, und zeige Dir auch, wie Du ohne die Fetch-Schleife auskommst. Das folgende Beispiel führt pro Eintrag in $kategorien eine DB-Query durch und sammelt mit array_merge
alles in $vorlagen zusammen. Fehler werden geprüft und mit einer Exception behandelt. D.h. du musst um den Aufruf von Vorlagen einen try/catch Block legen, aber dafür hast Du einen definierten Weg, wie Du Fehlermeldungen aus der Funktion hinausbekommst ohne dafür den Returncode umdeuten zu müssen.
Beachte, dass ich den Bind VOR der Schleife mache und auch kein & hinschreibe - das wäre PHP4 Style (oder sogar 3?) und ist heute falsch. Wenn eine Funktion ihre Parameter als Referenz empfängt, erzeugt PHP die Referenz beim Aufruf implizit. Ich will diese Lösung nicht als "besser" darstellen; Nachteile hatte ich schon genannt. Ich schreibe sie nur auf damit Du weißt was ich gemeinte hatte.
function Vorlagen($mysqli, $kategorien) {
$vorlagen = [];
if (!$stmt = $mysqli->prepare("SELECT ... WHERE kategorie = ?"))
throw new Exception("Prepare fehlgeschlagen: ".$mysqli->error);
$kat = "";
if (!$stmt->bind_param("s", $kat) { // Kein & in den Aufruf!
throw new Exception("Bind fehlgeschlagen ".$mysqli->error);
foreach ($kategorien as $kat) {
if (!$stmt->execute())
throw new Exception("execute fehlgeschlagen ".$mysqli->error);
$result = $stmt->get_result();
if ($result === FALSE)
throw new Exception("get_result fehlgeschlagen ".$mysqli->error);
$rows = $result->fetch_all(MYSQLI_ASSOC);
$result->free(); // WICHTIG!
if (is_array($rows))
$vorlagen = array_merge($vorlagen, $rows);
}
return $vorlagen;
}
Die Variante mit flexiblem Binding - RESPEKT!. Den call_user_func_array wollte ich Dir nicht zumuten, aber da habe ich deine PHP-Kenntnisse falsch eingeschätzt. Ein paar Tipps dazu:
Fragezeichenliste ohne substr:
// Dein Code
$s = substr( str_repeat( ' , ?' , count( $values ) ) , 2 );
// Zwei Alternativen dazu:
$s = '?' . str_repeat( ', ?' , count( $values ) - 1 );
$s = implode(',', array_fill(0, count($values), '?'));
Alternative 2 hat einen Fallstrick: count($values)==0. Das passiert, wenn keine Kategorie angehakt ist. Aber in dem Fall ist deine Query ohnehin so nicht brauchbar, das musst Du vorher abfangen. Ich denke, ohne Kategorien startest Du gar nicht erst die Suche...
String-Parsing durch double-quote Strings - magst Du das nicht?
// Dein Code
$stmt = $mysqli->prepare('SELECT ... WHERE kategorie IN (' .$s. ')');
// Mit String-Parsing:
$stmt = $mysqli->prepare("SELECT ... WHERE kategorie IN ($s)");
Referenzbildung geht einfacher:
// Dein Code
foreach ( $values as $k => $v ) {
${ 'varvar' . $k } = $v;
$params[] = &${ 'varvar' . $k };# provide references
}
// Alternative ohne dynamisch benannte Temp-Variablen
foreach ( $values as &$v ) { // Beachte das &
$params[] = &$v; // Nochmal Reference! Sonst klappt's nicht
}
Und auch bei dieser Lösung kannst Du mit einem Result-Objekt und fetch_all den bind_result und die Fetch-Schleife sparen.
Rolf
sumpsi - posui - clusi