Heim >Backend-Entwicklung >PHP-Problem >In drei Minuten lernen Sie das Initialisierungs-PDO und die ursprünglichen SQL-Anweisungsoperationen in PHP kennen.

In drei Minuten lernen Sie das Initialisierungs-PDO und die ursprünglichen SQL-Anweisungsoperationen in PHP kennen.

醉折花枝作酒筹
醉折花枝作酒筹nach vorne
2021-06-21 15:26:062135Durchsuche

Dieser Artikel stellt Ihnen das Initialisierungs-PDO und die ursprünglichen SQL-Anweisungsoperationen in PHP vor. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

In drei Minuten lernen Sie das Initialisierungs-PDO und die ursprünglichen SQL-Anweisungsoperationen in PHP kennen.

PDO ist zum De-facto-Standard für den Betrieb von Datenbanken in PHP geworden. Einschließlich aktueller Frameworks und verschiedener Klassenbibliotheken verwenden alle PDO als Datenbankverbindungsmethode. Grundsätzlich verwenden wir MySQL nur zum Betreiben der Datenbank, wenn wir einfachen Testcode oder kleine Funktionen schreiben. Beachten Sie, dass die normale MySQL-Erweiterung veraltet ist!

PDO-Instanz

Schauen wir uns zunächst an, wie eine PDO-Instanz initialisiert wird.

$dns = 'mysql:host=localhost;dbname=blog_test;port=3306;charset=utf8';
$pdo = new PDO($dns, 'root', '');

Unter normalen Umständen können wir ein PDO-Objekt erhalten, indem wir die Konstruktionsparameter übergeben, wenn wir es direkt instanziieren. Auf diese Weise haben wir eine Verbindung zur Datenbank hergestellt. Wenn die Verbindung fehlschlägt, also ein Problem mit den geschriebenen Parametern vorliegt, wird direkt bei der Instanziierung eine Ausnahme gemeldet.

Zu den Parametern des PDO-Objekts gehören DNS-Informationen, Benutzername, Passwort und ein weiterer Parameter, der einige Eigenschaften der PDO-Verbindung festlegen kann. Wir werden später seine Verwendung sehen.

dns-Parameter

Der erste Parameter des PDO-Konstruktionsparameters ist eine DNS-Zeichenfolge. Verwenden Sie in dieser Zeichenfolge Semikolons, um verschiedene Parameterinhalte zu trennen. Der Inhalt, der darin definiert werden kann, umfasst:

  • DSN-Präfix, das ist der Datenbanktyp, mit dem wir eine Verbindung herstellen möchten. MySQL-Datenbanken werden im Allgemeinen direkt mit MySQL definiert: Auf diese Weise.

  • host, die Verbindungsadresse, hier stellen wir eine Verbindung zur lokalen Datenbank her. localhost

  • port, die Portnummer, MySQL ist standardmäßig 3306, Sie müssen nicht schreiben

  • dbname, der Name von die zu verbindende Datenbank

  • unix_socket, Sie können die MySQL-Unix-Socket-Datei angeben

  • charset, den Verbindungszeichensatz

Wir können eine Funktion verwenden, um zu sehen, welche Datenbankerweiterungen in der aktuellen PHP-Umgebung unterstützt werden :

print_r(PDO::getAvailableDrivers());exit;
// Array
// (
//     [0] => dblib
//     [1] => mysql
//     [2] => odbc
//     [3] => pgsql
//     [4] => sqlite
// )

PDO-Objekt Der letzte Parameter des Attributs

PDO-Konstruktionsparameter kann einige Attribute der Verbindung festlegen, wie zum Beispiel:

$pdo = new PDO($dns, 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
showPdoAttribute($pdo);
// ……
// PDO::ATTR_ERRMODE: 2
// ……

showPdoAttribute() Methode ist eine von uns gekapselte Funktion, um alle Verbindungsattribute anzuzeigen.

// 显示pdo连接属性
function showPdoAttribute($pdo){
    $attributes = array(
        "DRIVER_NAME", "AUTOCOMMIT", "ERRMODE", "CASE", "CLIENT_VERSION", "CONNECTION_STATUS",
        "ORACLE_NULLS", "PERSISTENT", "SERVER_INFO", "SERVER_VERSION"
    );
    
    foreach ($attributes as $val) {
        echo "PDO::ATTR_$val: ";
        echo $pdo->getAttribute(constant("PDO::ATTR_$val")) . "\n";
    }
}

In dieser Funktion verwenden wir die Methode getAttribute() der PDO-Instanz, um den entsprechenden Attributwert abzurufen. Wenn PDO::ATTR_ERRMODE nicht festgelegt ist, ist sein Standardwert 0, was dem Wert entspricht, der der Konstante PDO::ERRMODE_SILENT entspricht. Im obigen Code setzen wir es auf PDO::ERRMODE_EXCEPTION und das Ergebnis der Anzeige der Attributausgabe wird 2.

Zusätzlich zum Festlegen von Attributen in den Parametern des Konstruktors können wir auch die Methode setAttribute() der PDO-Instanz verwenden, um den Attributwert von PDO festzulegen.

pdo2 = new PDO($dns, 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

echo $pdo2->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE), PHP_EOL;
// 4

// 设置属性
$pdo2->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
echo $pdo2->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE), PHP_EOL;
// 2

In diesem Code setzen wir PDO::ATTR_DEFAULT_FETCH_MODE auf PDO::FETCH_ASSOC. Auf diese Weise werden bei Abfragen über diese $pdo2-Verbindung die Ausgabeergebnisse in Form von Array-Schlüssel-Wert-Paaren zurückgegeben. Wir werden sofort mit der Untersuchung abfragebezogener Funktionen beginnen.

Abfrageanweisung

In den meisten Fällen verwenden wir bei der Verwendung von PDO dessen Vorverarbeitungsfunktionen zum Schreiben von SQL-Anweisungen. Erstens ist die Leistung besser und zweitens ist es sicherer. Lassen Sie uns heute jedoch nicht über Vorverarbeitungsprobleme sprechen. Lassen Sie uns einige verwandte Funktionen auf die primitivste Art und Weise der direkten Ausführung von SQL-Anweisungen erlernen.

Normale Abfrage und Durchquerung

// 普通查询 - 遍历1
$stmt = $pdo->query('select * from zyblog_test_user limit 5');
foreach ($stmt as $row) {
    var_dump($row);
}

// array(8) {
//     ["id"]=>
//     string(3) "204"
//     [0]=>
//     string(3) "204"
//     ["username"]=>
//     string(5) "three"
//     [1]=>
//     string(5) "three"
//     ["password"]=>
//     string(6) "123123"
//     [2]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "ccc"
//     [3]=>
//     string(3) "ccc"
//   }
//   ……

// 普通查询 - 遍历2
$stmt = $pdo->query('select * from zyblog_test_user limit 5');

while ($row = $stmt->fetch()) {
    var_dump($row);
}

// array(8) {
//     ["id"]=>
//     string(3) "204"
//     [0]=>
//     string(3) "204"
//     ["username"]=>
//     string(5) "three"
//     [1]=>
//     string(5) "three"
//     ["password"]=>
//     string(6) "123123"
//     [2]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "ccc"
//     [3]=>
//     string(3) "ccc"
//   }
//   ……

Die query()-Methode einer PDO-Instanz führt eine Abfrageanweisung aus und gibt ein PDOStatement-Objekt zurück. Durch Durchlaufen dieses Objekts können Sie den abgefragten Datenergebnissatz erhalten.

Im Code verwenden wir zwei Methoden zum Durchlaufen, aber tatsächlich haben sie den gleichen Effekt. Hier möchten wir uns auf das Format der zurückgegebenen Daten konzentrieren. Es ist ersichtlich, dass die Daten im Array-Format zurückgegeben werden, und zwar in zwei Formen: Eine ist der von der Datenbank definierte Schlüsselname und die andere ist eine tiefgestellte Form.

Abfrageergebnismenge (Array, Objekt)

Tatsächlich benötigen wir in den meisten Fällen nur Daten in Form von Schlüssel-Wert-Paaren von Datenbankschlüsselnamen. Es gibt zwei Möglichkeiten, dies zu tun. Eine besteht darin, die $pdo2-Verbindung direkt mit dem oben definierten Standardattribut PDO::ATTR_DEFAULT_FETCH_MODE zu verwenden, und die andere darin, beim Abfragen Attribute für die query()-Methode anzugeben.

$stmt = $pdo2->query('select * from zyblog_test_user limit 5');
foreach ($stmt as $row) {
    var_dump($row);
}
// array(4) {
//     ["id"]=>
//     string(1) "5"
//     ["username"]=>
//     string(3) "two"
//     ["password"]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "bbb"
//   }
//   ……

$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_ASSOC);
foreach ($stmt as $row) {
    var_dump($row);
}
// array(4) {
//     ["id"]=>
//     string(1) "5"
//     ["username"]=>
//     string(3) "two"
//     ["password"]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "bbb"
//   }
//   ……

Natürlich können wir die Daten auch direkt in das Objektformat zurückgeben. Ebenso können wir auch vordefinierte Konstanten verwenden, um query() oder die Attribute der PDO-Instanzverbindung anzugeben.

$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_OBJ);
foreach ($stmt as $row) {
    var_dump($row);
}
// object(stdClass)#4 (4) {
//     ["id"]=>
//     string(1) "5"
//     ["username"]=>
//     string(3) "two"
//     ["password"]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "bbb"
//   }
//   ……

Abfrageergebnismenge (Klasse)

Die Objekte in der Ergebnismenge, die in der oben genannten Form von Objekten zurückgegeben werden, sind vom Typ stdClass, dem Standardklassentyp von PHP. Können wir also selbst eine Klasse definieren und nach Abschluss der Abfrage direkt deren Ergebnismenge generieren? Genau wie ein ORM-Framework vervollständigt es die Zuordnung von Daten zu Objekten. Nachdem ich gesagt habe, dass es natürlich möglich ist, schauen Sie sich einfach den Code an.

class user
{
    public $id;
    public $username;
    public $password;
    public $salt;

    public function __construct()
    {
        echo 'func_num_args: ' . func_num_args(), PHP_EOL;
        echo 'func_get_args: ';
        var_dump(func_get_args());
    }
}

class user2
{

}
// 返回指定对象
$u = new user;
$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_INTO, $u);
foreach ($stmt as $row) {
    var_dump($row);
}
// object(user)#3 (4) {
//     ["id"]=>
//     string(1) "5"
//     ["username"]=>
//     string(3) "two"
//     ["password"]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "bbb"
//   }
//   ……

// 空类测试
$u = new user2;
$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_INTO, $u);
foreach ($stmt as $row) {
    var_dump($row);
}

// object(user2)#2 (4) {
//     ["id"]=>
//     string(1) "5"
//     ["username"]=>
//     string(3) "two"
//     ["password"]=>
//     string(6) "123123"
//     ["salt"]=>
//     string(3) "bbb"
//   }
//   ……

在这段代码中,我们定义了两个类,user 类有完整的和数据库字段对应的属性,还定义了一个构造方法(后面会用到)。而 user2 类则是一个空的类。通过测试结果来看,类的属性对于 PDO 来说并不重要。它会默认创建数据库查询到的字段属性,并将它赋值给对象。那么假如我们定义了一个 const 常量属性并给予相同的字段名称呢?大家可以自己尝试一下。

对于 user 和 user2 来说,我们将它实例化了并传递给了 query() ,并且指定了结果集格式为 PDO::FETCH_INTO ,这样就实现了获取对象结果集的能力。但是 PDO 远比你想象的强大,我们还可以直接用类模板来获取查询结果集。

// 根据类返回指定对象
$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_CLASS, 'user', ['x1', 'x2']);
foreach ($stmt as $row) {
    var_dump($row);
}
// func_num_args: 2
// func_get_args: array(2) {
//   [0]=>
//   string(2) "x1"
//   [1]=>
//   string(2) "x2"
// }
// object(user)#4 (4) {
//   ["id"]=>
//   string(1) "5"
//   ["username"]=>
//   string(3) "two"
//   ["password"]=>
//   string(6) "123123"
//   ["salt"]=>
//   string(3) "bbb"
// }
// ……

query() 方法直接使用查询结果集模式为 PDO::FETCH_CLASS ,并传递一个类模板的名称,PDO 就会在当前代码中查找有没有对应的类模板,获得的每个结果都会实例化一次。在这里,我们又多了一个参数,最后一个参数是一个数组,并且给了两个元素。估计有不少小伙伴已经看出来了,这个参数是传递给类的构造方法的。记住,使用这个模式,每个元素都会实例化一次,结果集中的每个元素都是新创建的类(object(user2)#3,#号后面的数字是不同的对象句柄id),而 PDO::FETCH_INTO 则是以引用的形式为每个元素赋值(object(user2)#3,#号后面的数字是相同的对象句柄id)。也就是说,我们使用 PDO::FETCH_INTO 模式的时候,修改一个元素的值,其它的元素也会跟着改变,如果使用一个数组去记录遍历的元素值,最后数组的结果也会是相同的最后一个元素的内容。

$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_INTO, $u);
$resArr = [];
foreach ($stmt as $row) {
    var_dump($row);
    $resArr[] = $row;
}
$resArr[0]->id = 55555;
print_r($resArr);
// Array
// (
//     [0] => user2 Object
//         (
//             [id] => 55555
//             [username] => two
//             [password] => 123123
//             [salt] => bbb
//         )

//     [1] => user2 Object
//         (
//             [id] => 55555
//             [username] => two
//             [password] => 123123
//             [salt] => bbb
//         )

//     [2] => user2 Object
//         (
//             [id] => 55555
//             [username] => two
//             [password] => 123123
//             [salt] => bbb
//         )

//     [3] => user2 Object
//         (
//             [id] => 55555
//             [username] => two
//             [password] => 123123
//             [salt] => bbb
//         )

//     [4] => user2 Object
//         (
//             [id] => 55555
//             [username] => two
//             [password] => 123123
//             [salt] => bbb
//         )

// )

如何解决这个问题呢?最简单的方式就是在数组赋值的时候加个 clone 关键字呗!

查询结果集(指定字段)

最后轻松一点,我们看下 query() 方法还可以指定查询的某一个字段。

// 只返回第几个字段
$stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_COLUMN, 2);
foreach ($stmt as $row) {
    var_dump($row);
}
// string(32) "bbff8283d0f90625015256b742b0e694"
// string(6) "123123"
// string(6) "123123"
// string(6) "123123"
// string(6) "123123"

增、删、改操作

除了查询之外的操作,我们也可以使用 exec() 方法来执行其他一些相应的 SQL 语句。

增加操作

$count = $pdo->exec("insert into zyblog_test_user(`username`, `password`, `salt`) value('akk', 'bkk', 'ckk')");
$id = $pdo->lastInsertId();

var_dump($count); // int(1)
var_dump($id); // string(3) "205"

exec() 返回的是影响的行数,如果我们执行这一条 SQL ,返回的就是成功添加了一行数据。如果要获得新增加数据的 id ,就要使用 lastInserId() 方法来获取。

$count = $pdo->exec("insert into zyblog_test_user(`username`, `password`, `salt`) value('akk', 'bkk', 'ckk', 'dkk')");
// Fatal error: Uncaught PDOException: SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1

执行错误的 SQL 语句,就像根据 PDO::ATTR_ERRMODE 属性的设置来返回错误信息。我们在最上面的实例化 PDO 代码中指定了错误形式是异常处理模式,所以这里直接就会报 PDOException 异常。

修改操作

// 正常更新
$count = $pdo->exec("update zyblog_test_user set `username`='aakk' where id='{$id}'");

var_dump($count); // int(1)

// 数据不变更新
$count = $pdo->exec("update zyblog_test_user set `username`='aakk' where id='{$id}'");
var_dump($count); // int(0)

// 条件错误更新
$count = $pdo->exec("update zyblog_test_user set `username`='aakk' where id='123123123123'");
var_dump($count); // int(0)
echo '===============', PHP_EOL;

同样的,在执行更新操作的时候,exec() 返回的也是受影响的行数。很多小伙伴会以这个进行判断是否更新成功,但如果数据没有修改,那么它返回的将是 0 ,SQL 语句的执行是没有问题的,逻辑上其实也没有问题。比如我们在后台打开了某条数据查看,然后并不想更新任何内容就直接点了提交,这时候不应该出现更新失败的提示。也就是说,在前端判断更新操作的时候,需要判断字段是否都有改变,如果没有改变的话那么不应该提示更新失败。这一点是业务逻辑上的考虑问题,如果你认为这样也是更新失败的话,那么这么报错也没有问题,一切以业务形式为主。

删除操作

$count = $pdo->exec("delete from zyblog_test_user where id = '{$id}'");
var_dump($count); // int(1)

// 条件错误删除
$count = $pdo->exec("delete from zyblog_test_user where id = '5555555555'");
var_dump($count); // int(0)

删除操作需要注意的问题和更新操作是一样的,那就是同样的 exec() 只是返回影响行数的问题,不过相对于更新操作来说,没有受影响的行数那肯定是删除失败的,没有数据被删除。同样的,这个失败的提示也请根据业务情况来具体分析。

总结

不学不知道,一学吓一跳吧,简简单的一个 PDO 的创建和语句执行竟然有这么多的内容。对于我们的日常开发来说,掌握这些原理能够避免很多莫名其妙的问题,比如上面 exec() 只是返回影响行数在业务开发中如何判断操作是否成功的问题就很典型。好了,这只是第一篇,后面的学习不要落下了哦!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP%E4%B8%AD%E7%9A%84PDO%E6%93%8D%E4%BD%9C%E5%AD%A6%E4%B9%A0%EF%BC%88%E4%B8%80%EF%BC%89%E5%88%9D%E5%A7%8B%E5%8C%96PDO%E5%8F%8A%E5%8E%9F%E5%A7%8BSQL%E8%AF%AD%E5%8F%A5%E6%93%8D%E4%BD%9C.php

推荐学习:php视频教程

Das obige ist der detaillierte Inhalt vonIn drei Minuten lernen Sie das Initialisierungs-PDO und die ursprünglichen SQL-Anweisungsoperationen in PHP kennen.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen