Funktionparameter innerhalb einer Schleife füllen

Wir sammeln alle Infos der Bonusepisode von Pokémon Karmesin und Purpur für euch!

Zu der Infoseite von „Die Mo-Mo-Manie“
  • Hallo zusammen,


    ich hab einen kleinen brainfuck mit PHP, MySQL und besonders mit der Funktion "bind_param", nämlich will ich eine global verwendbare Funktion für jede SQL-Anweisung.
    Bislang ist für die Anweisung "INSERT INTO" folgendes entstanden.


    PHP: sql.functions.php
    function insert($valuearray,$table,$connrw,$pattern){  $i=0  foreach($valuearray as $key => $value)  {    $insertionkeys.= '?,';    $insertionvalues.= '?,';    $allkeys.='$keys[$i],';    $allvalues.='$values[$i],';    $keys[$i]=$key;    $values[$i]=$value;    $i++;  }  // Daher dass WCF die Funktion substr gar nicht mag kürze ich hier ab, dass  // hier von den vier Variablen nur das überschüssige Komma entfernt wird  $insertion='INSERT INTO ? ('.$insertionkeys.') VALUES ('.$insertionvalues.');';  $insprep=$connrw->prepare($insertion);  $insprep->bind_param($pattern,$table,$allkeys,$allvalues);  if(!($insprep->execute()))  {    echo 'Eintrag konnte nicht hinzugefügt werden';  }}


    Ich hab als Problem, dass die Tabellen nicht immer die gleiche Anzahl an Spalten haben. Ich hab mir halt gedachte, dass ich in einer Variable einfach alle Spaltennamen und die dazugehörigen Werte speicher, also müsste dann die beiden Variablen am Ende so aussehen.


    PHP
    $allkeys = $key1,$key2,$key3,...,$keyn;
    $allvalues = $value1,$value2,$values3,...,$valuen;

    Ich frag mich jetzt, ob dies überhaupt möglich wäre, sprich, dass die Variablen als Variable oder als String behandelt werden...und was als Alternative möglich wäre...

    Analyse, Investigate, Fix, Improve

    Rächdshraipfelähr sind Special Effects meiner Tastatur

    Einmal editiert, zuletzt von Khanivore ()

  • Tabellen- und Spaltennamen können keine Variablen sein, deshalb wirst du zumindest diese direkt in den Query hineinbasteln müssen.


    Mein Ansatz würde in etwa so aussehen. Die Funktion setzt voraus, dass sowohl der Tabellenname als auch die Spaltennamen entweder nicht von Benutzern angefasst werden können oder vorher entsprechend bereinigt wurden. Wenn das nicht der Fall sein sollte, fehlt hier Code um SQL Injections zu vermeiden (nichts hindert mich daran, in die tabelle Users` VALUES (); DROP TABLE Users; -- etwas einzufügen und damit "aus Versehen" die Users Tabelle zu löschen).

    Wer Syntax- oder Logikfehler findet, darf sie behalten. Disclaimer: Komplett ungetestet, weil keine PHP-Umgebung zur Hand.

    FC (PKMN Y): 3282-3144-2343 — Safarityp: Pflanze (Maracamba, Folikon, Tangela) — Bei Interesse schickt mir einfach ne PM ;)


    Testet meine Pokemon-Checkliste für Gen. 1 bis 6 (für Sammler, und solche die es werden wollen – jetzt mit vollständiger Habitatsliste für alle Editionen – OR/AS noch minimal unvollständig)

  • Mein Ansatz würde in etwa so aussehen. Die Funktion setzt voraus, dass sowohl der Tabellenname als auch die Spaltennamen entweder nicht von Benutzern angefasst werden können oder vorher entsprechend bereinigt wurden. Wenn das nicht der Fall sein sollte, fehlt hier Code um SQL Injections zu vermeiden (nichts hindert mich daran, in die tabelle Users` VALUES (); DROP TABLE Users; -- etwas einzufügen und damit "aus Versehen" die Users Tabelle zu löschen).

    MySQL-Injection ist bereits in der Funktion berücksichtigt. Mit Hilfe des Strings in der Variablen Länge lege ich fest, wo ein bestimmter Datentyp sein soll.
    Aus INSERT INTO ? (?,?,?) VALUES (?,?,?) kann ich jetzt genau definieren, dass Ich in 1 bestimmte Tabelle 3 bestimmte Werte in die jeweiligen Spalten einfügen. Mit Hilfe von bind_param (Werte, Pattern) wird dann jedes ? durch einen Wert mit dem dazugehörigen Pattern ersetzt, damit wird die MySQL-Injection verhindert.
    Aber die Methode mit den Arrays ist auch ein guter Ansatz, dafür dank ich dir schon mal^^


    return ist nicht notwendig, da ich oben drüber schon eine Ausgabe tätige, wenn etwas nicht funktioniert hat.
    (Kann die PHP-Funktionen ebenfalls noch nicht testen, da Ich keine abgeschottete Non-productive Umgebung gerade verfügbar habe)

  • Das Problem ist, dass AFAIK INSERT INTO ? (?,?,?) nicht geht, weil MySQL an der Stelle überall konkrete Namen erwartet. Nur deshalb fügt meine Version da die Namen direkt ein (und ist damit in sachen Tabellenname und Spaltennamen anfällig für SQL-Injection).


    Und während DU mit der Ausgabe im Fehlerfall wissen wirst, dass etwas schiefgegangen ist, kann das Programm nicht darauf reagieren (und zum Beispiel darauf verzichten, von dem fehlgeschlagenen Datensatz abhängige weitere Datensätze einzufügen).

    FC (PKMN Y): 3282-3144-2343 — Safarityp: Pflanze (Maracamba, Folikon, Tangela) — Bei Interesse schickt mir einfach ne PM ;)


    Testet meine Pokemon-Checkliste für Gen. 1 bis 6 (für Sammler, und solche die es werden wollen – jetzt mit vollständiger Habitatsliste für alle Editionen – OR/AS noch minimal unvollständig)

  • Die Funktion mysqli->prepare nutzt jedes einzelne Fragezeichen, um einen bestimmten Wert dort einzufügen. Mit bind_param wird dieser bestimmte Wert eingesetzt, solange dieser Wert diesem Pattern entspricht.
    https://www.w3schools.com/php/…l_prepared_statements.asp


    Diese Ausgabe soll so nur im Falle von einem Berechtigungsfehler erscheinen. Im Normalfall ist der Input immer gleichmäßig, sprich es gibt genauso viele Keys (Input name) wie Werte (Werte halt).


    Ende mit Off-Topic, ich hab das nämlich gut durchdacht. Aber das hilft beim Ansatz weiter, weil pro Pattern brauch ich 1 Variable. Die Anzahl an Spalten, sowie die Anzahl an Werte sind gleichmäßig variabel.


    Daher meine Frage, ob die Variable für alle Variablen der Spalte (Grammatikfehler könnt Ihr behalten...) nur die Variablen einfügt, oder ob dort jede Variable in der Variable eingesetzt wird..


    Sprich ob dann am Ende "INSERT INTO Tabelle1 (Spalte1, Spalte2) VALUES (Wert1, Wert2)" steht, oder leider "INSERT INTO Tabelle1 ($key[0], $key[1]) VALUES ($value[0], $value[1])"...

  • Ich könnte mir vorstellen, dass dabei ein Fehler wie 'konnte Array nicht in String wandeln' oder sowas entsteht. Wobei ich zugeben muss, dass ich bisher noch nie ganze Arrays in Datenbanken gespeichert habe.


    Vllt helfen dir die Funktionen json_encode() und json_decode() weiter


    Edit:
    Ach nee, hab mich verschaut :grin:
    Theoretisch müsste das herauskommen, wie du es dir vorgestellt hast


    Was sagt denn PHP und/oder MYSQL wenn du den Code ausführst?
    Und steht dann in den Tabellen, was drin stehen soll?

  • Worauf ich hinaus will, ist, dass Tabellen- und Spaltennamen keine Parameter sein können und deshalb dein Ansatz mit INSERT INTO ? (?,?,?) so nicht funktionieren kann.


    Außerdem kannst du nicht einfach zwei egal wie formatierte Strings an bind_param übergeben und hoffen, dass er daraus etwas anderes macht als zwei String-Argumente. Du musst jedes Argument einzeln übergeben. Und String-Interpolation int PHP funktioniert nur mit doppelten Anführungszeichen, Strings mit einfachen Anführungszeichen werden so verwendet wie sie da stehen. ("$foo" enthält den Inhalt von $foo, '$foo' bleibt wie es ist).

    FC (PKMN Y): 3282-3144-2343 — Safarityp: Pflanze (Maracamba, Folikon, Tangela) — Bei Interesse schickt mir einfach ne PM ;)


    Testet meine Pokemon-Checkliste für Gen. 1 bis 6 (für Sammler, und solche die es werden wollen – jetzt mit vollständiger Habitatsliste für alle Editionen – OR/AS noch minimal unvollständig)