• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

variable INSERT funktion

Mad Dog

Mitglied
hey liebe Leute,

nachdem mir mermshaus in einem thread versichert hat, dass das was ich vorhabe nicht SQL Injektion gefaehrdet ist, habe ich damit angefangen.

hier zunaechst der code, denn ich bereits habe:
Code:
    public function insert($table, $rows, $values, $type)
    {
      $sql = 'INSERT INTO '.$table.' (';      
      
          for ($i = 0; $i <= (sizeof($rows)-1); $i++)
          {
              if (!($i == (sizeof($rows)-1)))
              {
                  $sql .= $rows[$i].', ';
              }
              else
              {
                  $sql .= $rows[$i];
              }
          }    
      $sql .= ') VALUES (';
      
          for ($i = 0; $i < sizeof($rows); $i++)
          {
              if (!($i == (sizeof($rows)-1)))
              {
                  $sql .= '?, ';
              }
              else
              {
                  $sql .= '?)';
              }
          }
          
          for ($i = 0; $i < (sizeof($values)-1); $i++)
          {
              $
          }
 
          if (!($this->mysqli_stmt->prepare($sql)))
            {
                $this->error[0] = $this->error;
                $this->error[1] = $this->errno;
                return FALSE;
            }
            else if (!($this->mysqli_stmt->bind_param($type, )))
            {
                $this->error[0] = $this->error;
                $this->error[1] = $this->errno;
                return FALSE;
            }
            else if (!($this->mysqli_stmt->execute()))
            {
                $this->error[0] = $this->error;
                $this->error[1] = $this->errno;
                return FALSE;
            }
            else
            {
                if (($this->mysqli_stmt->affected_rows) == -1)
                {
                    return FALSE;
                }
                else if (($this->mysqli_stmt->affected_rows) == 0)
                {
                    return FALSE;
                }
                else
                {
                    return TRUE;
                }
            }
      
    }
Die funktion erwartet eine Variable $table, die man braucht um die Tabelle auszuwaehlen.
$rows ist ein array, welches die Spalten enthaelt, in welche etwas eingetragen werden soll.
$values ist ebensfals ein array und enthaelt die daten die eingetragen werden sollen.
$type ist speziel fuer die funktion mysqli_stmt_bind_param(), welche den typen der spalte enthaelt (s fuer string, i fuer integer etc).

bis dahin kein problem.
das problem liegt da, dass man NICHT weiss wie viele werte in $value sind. mittels sizeof() kein problem das herauszufinden.

Jedoch will ich, dass der mysqli_stmt_bind_param() befehl am ende so aussieht:
Code:
else if (!($this->mysqli_stmt->bind_param($type, $value[0], $value[1], $value[2], $value[3])))
ich hoffe ihr versteht meine frage :)

mfg
marius

EDIT:
fals es weiterhilft:
Ich habe einen String, der genau die benötigten Parameter liefert. Jedoch ist es ein String und somit unnutz fuer das Problem denke ich mal!
 
Zuletzt bearbeitet:
nachdem mir mermshaus in einem thread versichert hat, dass das was ich vorhabe nicht SQL Injektion gefaehrdet ist, habe ich damit angefangen.

Ich habe gesagt, dass die bind_param-Funktion escapet.

PHP:
$sql = 'INSERT INTO '.$table.' ... ';

Sowas ist noch immer anfällig für Injections. (→ PHP: mysqli_escape_string - Manual)

Das Problem mit bind_param und der variablen Anzahl an zu übergebenden Variablen kann per call_user_func_array gelöst werden. Dazu:

PHP: mysqli_stmt::bind_param - Manual

Note: Care must be taken when using mysqli_stmt_bind_param() in conjunction with call_user_func_array(). Note that mysqli_stmt_bind_param() requires parameters to be passed by reference, whereas call_user_func_array() can accept as a parameter a list of variables that can represent references or values.

Das scheint so für PHP 5.3 nicht mehr zu stimmen. Siehe Kommentar auf derselben Seite: PHP: mysqli_stmt::bind_param - Manual

Habe dir mal lauffähigen Code (quick & dirty) zurechtgebastelt, aber so ganz easy ist das leider alles nicht, auch vom Konzept her. Eigentlich werden Prepared Statements auch nicht auf diese Weise (neu 'präpariert' für nur eine Query) verwendet. Das wäre eher was für die Standard-Queryfunktion.

Die Behandlung der MySQLi-Objekte ist in diesem Beispiel auch nicht toll. Ich habe sie bloß schnell erstellt und nicht weiter drüber nachgedacht. (Der Einfachheit halber habe ich auch die Error-Geschichte rausgenommen.)

PHP:
<?php

class Test
{
    protected $_mysqli_stmt;
    protected $_mysqli;

    public function __construct($server, $user, $password, $db)
    {
        $this->_mysqli = new mysqli($server, $user, $password);
        $this->_mysqli->select_db($db);
        $this->_mysqli_stmt = $this->_mysqli->stmt_init();
    }

    /**
     *
     * @see http://www.php.net/manual/en/mysqli-stmt.bind-param.php#96770
     */
    protected function _refValues($arr){
        if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+
        {
            $refs = array();
            foreach($arr as $key => $value)
                $refs[$key] = &$arr[$key];
            return $refs;
        }
        return $arr;
    } 

    public function insert($table, $data)
    {
        $sql = 'INSERT INTO `' . $this->_mysqli->escape_string($table) . '`';

        // Feldnamen hinzufügen
        $escapedKeys = array_map(array($this->_mysqli, 'escape_string'), array_keys($data));
        $sql .= ' (`' . implode('`, `', $escapedKeys) . '`)';
     
        // Platzhalter für Werte hinzufügen
        $sql .= ' VALUES (' . implode(', ', array_fill(0, count($data), '?')) . ')';

        // Feldtypen ermitteln
        $type = '';
        $values = array_values($data);

        foreach ($values as $value) {
            if (is_int($value)) {
                $type .= 'i';
            } else if (is_double($value)) {
                $type .= 'd';
            } else {
                $type .= 's';
            }
        }

        if (!($this->_mysqli_stmt->prepare($sql))) {
            return FALSE;
        }

        if (!call_user_func_array(array($this->_mysqli_stmt, "bind_param"),
            array_merge(array($type), $this->_refValues($data)))
        ) {            
            return FALSE;
        }

        if (!($this->_mysqli_stmt->execute())) {
            return FALSE;
        }
        
        if (($this->_mysqli_stmt->affected_rows) <= 0) {
            return FALSE;
        }
        
        return TRUE;
    }
}

$t = new Test('localhost', 'user', 'pass', 'dbname');

$data = array(
    'headline'  => 'db-test',
    'text'      => 'eins, zwei, drei, vier',
    'author_id' => 12
);

$f = $t->insert('news', $data);

if ($f == false) {
    echo 'Fehler';
} else {
    echo 'Erfolg';
}
 
Zurück
Oben