English / Deutsch | Druckversion
Twitter
twitter

PHP / MySQL / PDO


Die MySQL Erweiterung wurde in PHP7 endgültig entfernt. Stattdessen kann man die MySQLi- oder PDO-Erweiterung verwenden. Ich bevorzuge PDO. Damit ist man nicht von der MySQL Datenbank abhängig.

Zu Beginn wirkt der Wechsel zu PDO kompliziert. Ich habe eine kleine Library (pdo.php) geschrieben um die Umstellung leicht durchführen zu können. Ich zeige auch ein paar PHP Code Beispiele.


Funktionsliste der pdo.php Library
Beispiele
SQL Injection verhindern
MySQL LIKE mit PDO bei Prepared Statements
Debugfunktionen von pdo.php
PDO::FETCH_BOTH oder PDO::FETCH_ASSOC
Kleines Beispiel mit pdo.php
Download pdo.php


Funktionsliste der pdo.php Library


 function SQL_Connect    ($user, $pass, $db, $host = "localhost", $charset = "utf8mb4");
 function SQL_Exec       ($pdo, $query, $values = false);
 function SQL_Fetch      ($pdo, $query, $values = false);
 function SQL_MultiFetch ($pdo, $query, $values = false);
 function SQL_LastID     ($pdo);
 function SQL_Error      ($e, $query);

Beispiele


Eine Zeile auslesen

MySQL:

1
2
3
4
5
6
7
 $query = "SELECT * FROM user
WHERE id = $id
LIMIT 1";

$result = mysql_query ($query, $conn);
if (!$result) die (mysql_error());
$read = mysql_fetch_array ($result);

Neu:

1
2
3
4
5
 $query = "SELECT * FROM user
WHERE id = $id
LIMIT 1";

$read = SQL_Fetch ($pdo, $query);

Mehrere Zeilen auslesen

MySQL:

1
2
3
4
5
6
7
8
9
10
 $query = "SELECT * FROM user
ORDER BY last_name";

$result = mysql_query ($query, $conn);
if (!$result) die (mysql_error());
while ($read = mysql_fetch_array ($result))
{
// Do something
echo $read["first_name"] . " " . $read["last_name"] . "<br />";
}

Neu:

1
2
3
4
5
6
7
8
9
 $query = "SELECT * FROM user
ORDER BY last_name";

$arr = SQL_MultiFetch ($pdo, $query);
foreach ($arr as $read)
{
// Do something
echo $read["first_name"] . " " . $read["last_name"] . "<br />";
}

Kommando ausführen

MySQL:

1
2
3
4
5
6
 $query = "DELETE FROM user
WHERE id = $id
LIMIT 1";

$result = mysql_query ($query, $conn);
if (!$result) die (mysql_error());

Neu:

1
2
3
4
5
 $query = "DELETE FROM user             
WHERE id = $id
LIMIT 1";

SQL_Exec ($pdo, $query);


SQL Injection verhindern


Bei MySQL verhindert man SQL Injections mit 'mysql_real_escape_string()'. Bei PDO wird dies mit Perpared Statements realisiert.

Bei Prepared Statements mit PDO wird als Platzhalter das Zeichen '?' oder sogenannte Named Parameters anstelle des Wertes in die Query geschrieben. Die Werte werden dann via Array übermittelt. Sie können die array() Funktionen von PHP verwenden, oder Arrays mittels '[' und ']' erstellen.

MySQL:

1
2
3
4
5
6
 $query = "INSERT INTO user (first_name, last_name)
VALUES ('" . mysql_real_escape_string ($_POST["first_name"]) . "',
'" . mysql_real_escape_string ($_POST["last_name"]) . "')";

$result = mysql_query ($query, $conn);
if (!$result) die (mysql_error());

Neu:

1
2
3
4
 $query = "INSERT INTO user (first_name, last_name)
VALUES (?, ?)";

SQL_Exec ($pdo, $query, [$_POST["first_name"], $_POST["last_name"]]);

Oder mit Named Parameters:

1
2
3
4
5
6
7
8
 $query = "INSERT INTO user (first_name, last_name)
VALUES (:first_name, :last_name)";

$named_params = [ ":first_name" => $_POST["first_name"],
":last_name" => $_POST["last_name"]
];

SQL_Exec ($pdo, $query, $named_params);


MySQL LIKE mit PDO bei Prepared Statement


Bei diesem Beispiel sollen alle User gesucht werden, bei denen der Nachname (last_name) mit dem Text von '$search' beginnt. Wir verwenden 'LIKE' und '%'.

MySQL:

1
2
3
4
5
6
7
8
9
10
 $query = "SELECT * FROM user
WHERE last_name LIKE '$search%'";

$result = mysql_query ($query, $conn);
if (!$result) die (mysql_error());
while ($read = mysql_fetch_array ($result))
{
// Do something
echo $read["first_name"] . " " . $read["last_name"] . "<br />";
}

Neu: Bei Prepared Statements wird '%' im Array angegeben (siehe Zeile 4).

1
2
3
4
5
6
7
8
9
 $query = "SELECT * FROM user
WHERE last_name LIKE ?";

$arr = SQL_MultiFetch ($pdo, $query, ["$search%"]);
foreach ($arr as $read)
{
// Do something
echo $read["first_name"] . " " . $read["last_name"] . "<br />";
}


Debugfunktionen von pdo.php


Es gibt verschiedene Einstellung für Debugausgabe.


PDO_DEBUG ist nicht definiert (default)

Bei einem Fehler wird der Text "SQL Error! Please contact the administrator." angezeigt.


PDO_DEBUG ist definiert

define ("PDO_DEBUG", "");

Bei einem Fehler wird der Text "SQL Error: " mit der Information vom System angezeigt.


PDO_DEBUG is defined with value 2

define ("PDO_DEBUG", "2");

Bei einem Fehler wird

  der Text "SQL Error: " mit der Information vom System angezeigt.
  das Problematische SQL Statement wird angezeigt.


PDO_DEBUG is defined with value 3

define ("PDO_DEBUG", "3");

Bei einem Fehler wird

  der Text "SQL Error: " mit der Information vom System angezeigt.
  das Problematische SQL Statement wird angezeigt.
  Sie sehen detailierte Tracebackinformationen mit Skriptnamen und Skriptzeilennummern.



PDO::FETCH_BOTH oder PDO::FETCH_ASSOC


PDO::FETCH_BOTH ist die Standardeinstellung in PHP. Die Daten im Rückgabe-Array sind doppelt enthalten. Einmal mit dem Feldnamen als Array-Key und einmal mit einer Indexnummer als Array-Key.

1
2
3
4
5
 $query = "SELECT first_name, last_name FROM user
WHERE id = $id
LIMIT 1";

$read = SQL_Fetch ($pdo, $query);

$read[0] und $read["first_name"] haben den selben Wertz z.B. "Max".

$read[1] und $read["last_name"] haben den selben Wert, z.B. "Mustermann".

Im Fall von SELECT COUNT(*) erhällt man mit PDO::FETCH_BOTH die Felder $read[0] und $read["COUNT(*)"].


Bei PDO::FETCH_ASSOC sind die Felder nur mit dem Feldnamen als Array-Key enthalten. Zum Beispiel $read["first_name"], $read["last_name"], $read["COUNT(*)"].

Ich bevorzuge PDO::FETCH_ASSOC. Dies wird in der SQL_Connect Funktion aktiviert. Entfernen Sie die Zeile wenn Sie PDO::FETCH_BOTH verwenden möchten.


Kleines Beispiel mit pdo.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php

 
include_once ("pdo.php");


 
// We want every debug information on an error.
 
define ("PDO_DEBUG""3");


 
// Connect to the database.
 
$pdo SQL_Connect ("dbuser""secret""mydb");


 
// Add some data.
 
$query "INSERT INTO user (first_name, last_name)
           VALUES (?, ?)"
;
           
 
SQL_Exec ($pdo$query, [$_POST["first_name"], $_POST["last_name"]]);   
 

 
// Get the ID of the new entry.
 
$id SQL_LastID ($pdo);


 
// Delete the entry.
 
$query "DELETE FROM user
           WHERE  id = 
$id
           LIMIT  1"
;

 
SQL_Exec ($pdo$query);

?>


Download pdo.php


Download pdo.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<?php
/*

  PDO SQL Routines by Elmar Hanlhofer 03/09/2018 https://www.plop.at
  Free to use. Comes without warranty.

 ------------------------------------------------------------

 function SQL_Connect    ($user, $pass, $db, $host = "localhost", $charset = "utf8mb4");
 function SQL_Exec       ($pdo, $query, $values = false);
 function SQL_Fetch      ($pdo, $query, $values = false);
 function SQL_MultiFetch ($pdo, $query, $values = false);
 function SQL_LastID     ($pdo);
 function SQL_Error      ($e, $query);

 ------------------------------------------------------------

 Define PDO_DEBUG for detailed error messages.

 PDO_DEBUG values:

    1: Print the error message.
    2: Print also the SQL Statement.
    3: Print SQL Statement and traceback with detailed information where the error occurs.

 Example: define ("PDO_DEBUG", "2");

*/

function SQL_Connect ($user$pass$db$host "localhost"$charset "utf8mb4")
{
    try
    {
        
$pdo = new PDO ("mysql:host=$host;dbname=$db;charset=$charset"$user$pass);
    }
    catch (
PDOException $e)
    {
        
SQL_Error ($e);
    }

    
$pdo->setAttribute (PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);

    
// Returned values are only indexed by column name.
    // Set it to PDO::FETCH_BOTH if you also want to have the 0-indexed column number in your result.
    
$pdo->setAttribute (PDO::ATTR_DEFAULT_FETCH_MODEPDO::FETCH_ASSOC);

    return 
$pdo;
}

function 
SQL_Exec ($pdo$query$values false)
{
    try
    {
        if (!
$values)
        {
            
$pdo->exec ($query);
        }
        else
        {
            
$stmt $pdo->prepare ($query);
            
$stmt->execute ($values);
            
$stmt null;
        }
    }
    catch (
PDOException $e)
    {
        
SQL_Error ($e$query);
    }
}

function 
SQL_Fetch ($pdo$query$values false)
{
    try
    {    
        if (!
$values)
        {
            return 
$pdo->query ($query)->fetch();
        }
        else
        {
            
$stmt $pdo->prepare ($query);
            
$stmt->execute ($values);
            
$arr $stmt->fetch ();
            
$stmt null;    
            return 
$arr;
        }
    }    
    catch (
PDOException $e)
    {
        
SQL_Error ($e$query);
    }
}

function 
SQL_MultiFetch ($pdo$query$values false)
{
    try
    {
        
$stmt $pdo->prepare ($query);
        if (!
$values)
        {
            
$stmt->execute ();
        }    
        else
        {    
            
$stmt->execute ($values);
        }
        
$arr $stmt->fetchAll ();
        
$stmt null;    
        return 
$arr;
    }    
    catch (
PDOException $e)
    {
        
SQL_Error ($e$query);
    }
}

function 
SQL_LastID ($pdo)
{
    return 
$pdo->lastInsertId();
}

function 
SQL_Error ($e$query)
{
    echo 
"<pre>";
    
    if (
defined ("PDO_DEBUG"))
    {
        echo 
"SQL Error: " $e->getMessage() . "\n\n";
    
        if (
PDO_DEBUG >= "2")
        {
            echo 
"$query\n\n";
        }
        
        if (
PDO_DEBUG == "3")
        {
            
// Print details like script name and line.
            
print_r ($e);
        }
    }
    else
    {
        echo 
"SQL Error! Please contact the administrator.";
    }

    echo 
"</pre>";

    
// Stop on error.
    
exit;
}
?>

© 2018 by Elmar Hanlhofer
Die Seite wurde zuletzt am 03/Sep/2018 geändert.