MySQL-Escape Schwierigkeiten

suntrop

Erfahrenes Mitglied
Hi. Ich nutze für einen Login die phpUserClass und dabei treffe ich gerade auf eine schwierige Situation. In der Klasse gibt es ein Methode die anhand eines Arrays Tabellenfelder aktualisiert.
PHP:
$updateArray = array(
  'lastVisit' => "'2009-11-29 18:35:43'",
  'loginCount' => 'loginCount+1',
  'lastLogin' => 'NOW()'
);
$user->updateProperty($updateArray);

Die Methode sieht so aus:
PHP:
public function updateProperty($properties)
  {
    if(is_array($properties) && count($properties) > 0)
    {
      $i=1;
      $query = "UPDATE ".$this->dbTable." SET ";

      foreach($properties AS $k => $v)
      {
        $query .= "".$this->escape($k)." = ".$this->escape($v)."".(($i++ < count($properties)) ? ', ' : ' ');
        #$query .= '`'.$this->escape($k)."` = '".$this->escape($v)."'".(($i++ < count($properties)) ? ', ' : ' ');
      }

      $query .= "WHERE ".$this->tbFields['userID']." = ".$this->userID."";
      if($this->mysqli->query($query))
        return true;
      else
      {
        $this->error($this->mysqli->error, __LINE__);
        return false;
      }
    }
  else
    return false;
  }

Was mich jetzt aushebelt ist, dass ich im aktuellen Fall keine Strings, sondern nur MySQL-Kommandos in das Array eintragen kann. Ein Datum 2009-11-29 19:35:07 führt zur Fehlermeldung:
Code:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'2009-11-29 19:35:07\', loginCount = loginCount+1, lastLogin = NOW() WHERE id =' at line 1

Das liegt an der escape() Methode:
PHP:
private function escape($str)
  {
    $str = get_magic_quotes_gpc() ? stripslashes($str) : $str;
    return $this->mysqli->real_escape_string($str);
    return $str;
  }

Wenn ich in updateProperty() das Query ändere
PHP:
$query .= '`'.$this->escape($k)."` = '".$this->escape($v)."'".(($i++ < count($properties)) ? ', ' : ' ');
(einfach Anführungsstriche für $v eingefügt)
… dann brauche ich den String im $updateArray nicht mehr mit Anführungsstrichen als String markieren. Dann kann ich allerdings keine MySQL-Kommandos mehr senden. Ein klassisches Dilemma :-)

Ich befürchte, dass die Art und Weise leider nur das eine oder andere (Strings oder SQL) zulässt und ich somit das ganze umschreiben muss. Vielleicht (die Hoffnung haben ich noch :-) ) geht es aber auch einfacher und ich komm nur nicht drauf.

Was habt ihr für einen Rat für mich? Wie kann ich das am besten lösen?

Danke erstmal dafür, dass du bis hierher gelesen hast :-) Sorry für das lange Posting.
 
Ja, recht hast du. Du kannst einfach keine Strings in Hochkommas in das update-Array schreiben. Normal sollte man meinen der Ausweg dazu laute "Prepared Statements". (Also Queries bei denen sich u.a. die DB um's escapen kümmert. http://php.net/manual/en/mysqli.prepare.php ) Das kannst du natürlich versuchen, ich schätze aber du wirst so oder so nicht umher kommen dein Konzept nochmal zu überdenken.
 
Da dachte ich, ich habe eine schöne Klasse gefunden, die alles kann :-)
Ok, vorher war die auf MySQL gemünzt und jetzt könnte ich wirklich rein auf MySQLi umschwenken und Prepared Statements nutzen. Das wird – für mich – nochmal ein ganz schöner Akt.

Danke für deine Antwort.
 
Immer gern. Gibt sicher auch noch tollere Möglichkeiten für deinen Fall, so ist ja nicht. Dafür bist du ja der Coder ;o) Aber wenn du auf MySQLi umschwenkst wird die Applikation immerhin auch noch nen Tacken schneller und sicherer =)
 
Natürlich geht das. Du musst entweder die Funktion updateProperty() anpassen oder eine neue Schreiben. Diejenige die du gefunden hast wurde nur für Zahlenwerte erstellt.

Du musst einfach noch den Feldtype auswerten.

Code:
SELECT COLUMN_NAME, DATA_TYPE
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE table_name = 'tbl_name'
 
hm, mir kommt es so vor, als würde dieser Teil:

PHP:
      foreach($properties AS $k => $v)
      {
        $query .= "".$this->escape($k)." = ".$this->escape($v)."".(($i++ < count($properties)) ? ', ' : ' ');
        #$query .= '`'.$this->escape($k)."` = '".$this->escape($v)."'".(($i++ < count($properties)) ? ', ' : ' ');
      }
schwierigkeiten macht :)


Probiere es mal so:
PHP:
foreach($properties AS $k => $v)
      {
        $query .= "".$this->escape($k)." = ".$this->escape($v)."".(($i+1 < count($properties)) ? ', ' : ' ');
        $i++;
        #$query .= '`'.$this->escape($k)."` = '".$this->escape($v)."'".(($i++ < count($properties)) ? ', ' : ' ');
      }
 
@KD3
Ich versteh zwar nicht so ganz, was die Code-Änderung macht. Aber es ändert sich bei der Fehlermeldung leider nichts.

@yaslaw
Ja, denke ich werde das abändern und die "automatische" escape-Funktion entfernen. Dann muss ich zwar wieder händisch und immer wieder neu die Eingaben escapen, aber ich habe dafür die Freiheit auch SQL-Kommandos auszuführen.

Vielleicht setzte ich jedoch auch auf Prepared Staements. Muss mich damit mehr beschäftigen, weiß nicht, ob ich dann wieder etwas "weglassen" muss.

Grüße
suntrop
 
Zurück