PHP Datenbankzugriff: MySQLi

From Coders.Bay Wiki
Jump to navigation Jump to search

https://web.cb-kompetenzen.at/datenbankanbindung-mit-php/

Verbindung aufbauen

<?php
// Die login.inc.php beinhaltet die Verbindung zur Datenbank. 
// Hierfür lege ich vier Variablen an für den Host, Passwort, User und Datenbanknamen
$host = "localhost";
$pw = "";
$user = "root";
$table = "lexikonsimple";
// Das MySQL Statement für die Verbindung zur Datenbank speichere ich ebenfalls in eine Variable ab. 
// Achtung, die Reihenfolge ist wichtig und kann NICHT verändert werden. 
// Diese Methode erwartet vier Parameter in genau der Reihenfolge.
$con = new mysqli($host, $user, $pw, $table);

// Check connection
// Damit ich eine Meldung bekomme, falls die Verbingung nicht funktioniert, schreib ich noch ein kleines if-Statement:
if($con->connect_errno){
    printf("Connect failed: %s\n", $con->connect_error);
    exit();
}
?>

Prepared Statements

  • Prepared Statements = einsatzfertige Muster für Abfragen in SQL-Datenbanksystemen, die keine Werte für die einzelnen Parameter enthalten. Stattdessen arbeiten diese Anweisungsmuster (auch Anweisungstemplates genannt) mit Variablen bzw. Platzhaltern, die erst innerhalb des Systems durch die tatsächlichen Werte ersetzt werden – anders als bei der manuellen Eingabe, wo die Werte bereits zum Zeitpunkt der Ausführung eines Befehls zugeordnet sind.
  • Der entscheidende Grund dafür, ist der Sicherheitsaspekt. Das wohl größte Problem an standardmäßigen Zugriffen auf Datenbanken ist die leichte Manipulation => SQL-Injection, bei der Code hinzugefügt oder angepasst wird, um an sensible Daten zu gelangen oder gänzlich die Kontrolle über das Datenbanksystem zu erlangen. Prepared Statements bieten eine solche Sicherheitslücke nicht, da ihnen erst innerhalb des Systems konkrete Werte zugeordnet werden.
  • Weiterer Grund: Einmal analysiert und kompiliert, können diese vom jeweiligen Datenbanksystem im Anschluss immer wieder verwendet werden (mit den jeweiligen, abgeänderten Werten). Dadurch verbrauchen Prepared Statements wesentlich weniger Ressourcen und sind schneller als manuelle Datenbankabfragen, wann immer es um SQL-Aufgaben geht, die wiederholt ausgeführt werden müssen.

SQL Injections

  • => Ausnutzen einer Sicherheitslücke in relationalen Datenbankensystemen, die bei der Dateneingabe auf die Sprache SQL zurückgreifen. Oft tritt eine SQL-Injection in Zusammenhang mit PHP- und ASP-Programmen auf, die auf ältere Interfaces zurückgreifen.
  • Mit gezielten Einsatz von Funktionszeichen schleust ein eigentlich unberechtigter Benutzer weitere SQL-Befehle ein und manipuliert die Einträge derart, dass er Daten verändern, löschen oder lesen kann. In gravierenden Fällen ist es sogar möglich, dass sich ein Angreifer auf diesem Wege den Zugriff auf die Kommandozeile des befehlsausführenden Systems und damit über den gesamten Datenbankserver verschafft

MySQLi & Prepared Statements

  • Mit bind_param() Variable mit Parameter verbinden
  • ssi sind die Typen der Parameter, gibt an, dass drei Parameter im Query sind, den ersten mit dem Typ string, den zweiten vom Typ string und den dritten vom Typ integer. Für Fließkommazahlen existiert noch der Wert d
  • Werte den Variablen zuweisen
  • mittels $statement->execute() wird der Prepared Statement an die Datenbank gesendet.
<?php
$mysqli = new mysqli("localhost", "user", "Password", "database");
if ($mysqli->connect_errno) {
    die("Verbindung fehlgeschlagen: " . $mysqli->connect_error);
}
$sql = "UPDATE user SET email = ?, passwort = ? WHERE id = ?";
$statement = $mysqli->prepare($sql);
$statement->bind_param('ssi', $email, $password, $id);

//Variablen Werte zuweisen
$id= 1;
$email = "ein@beispiel.de";
$password = "neues passwort";
$statement->execute();
?>

Datensätze abrufen

Zum Abrufen und Ausgeben von Datensätzen existieren die Methoden $result->fetch_assoc() und $result->fetch_object()

<?php
$mysqli = new mysqli("localhost", "user", "password", "database");
if ($mysqli->connect_errno) {
    die("Verbindung fehlgeschlagen: " . $mysqli->connect_error);
}
$id = 100;
$sql = "SELECT * FROM tabelle WHERE id < ?";
$statement = $mysqli->prepare($sql);
$statement->bind_param('i', $id);
$statement->execute();

$result = $statement->get_result();


while($row = $result->fetch_object()) {
    echo $row->spaltenname;
}

//Alternativ mit fetch_assoc():
while($row = $result->fetch_assoc()) {
    echo $row['spaltenname'];
}

?>

Datensatzabfrage ohne Parameter

Da es keine Parameter gibt, kann ->query($sql) verwendet werden ansonsten immer Prepared Statements verwenden

<?php
$mysqli = new mysqli("localhost","root","","kundendaten");
if ($mysqli -> connect_errno) {
  die("Fehler: " . $mysqli -> connect_error);
}

$sql = "SELECT * FROM kunden"; 
$result = $mysqli->query($sql);

while($row = $result->fetch_assoc()) {
  print("Vorname: ".$row['kundenvorname'])."\n";
}

Anzahl der Zeilen

<?php

$mysqli = new mysqli("localhost", "root", "", "php-einfach");
if ($mysqli->connect_errno) {
  die("Verbindung fehlgeschlagen: " . $mysqli->connect_error);
}

// Prepared statement mit INSERT/DELETE/UPDATE-Anweisung für $statement
// Um Anzahl der betroffenen Zeilen von UPDATE, DELETE oder INSERT-Anweisungen zu erhalten, 
// existiert das Feld $statement->affected_rows
$statement->execute();
$count = $statement->affected_rows;
echo $count;



// Prepared statement mit SELECT-Anweisung für $statement
// Um die Anzahl der Zeilen einer SELECT-Anweisung zu erhalten, existiert das Feld $result->num_rows
$statement->execute();
$result = $statement->get_result();
$count = $result->num_rows;
echo $count;

?>
<pre>

=== MySQL Fehlermeldung ===

<pre>
<?php
//Prepared statement in $statement
if(!$statement->execute()) {
  echo "Query fehlgeschlagen: ".$statement->error;
}
?>