Recommandations d'apprentissage associées : Tutoriel MySQL
Concernant les instructions préparées, nous les avons brièvement présentées dans le tutoriel précédent. Nous pouvons les comparer avec les modèles de vue. Les instructions préparées sont des modèles d'instructions SQL prédéfinis. La valeur est remplacée par un espace réservé :
INSERT INTO REGISTRY (name, value) VALUES (?, ?) INSERT INTO REGISTRY (name, value) VALUES (:name, :value)
Ensuite, avant que l'instruction SQL ne soit réellement exécutée, la valeur du paramètre spécifique est liée et mappée à l'espace réservé correspondant via une méthode API spécifique. Tout comme le modèle de vue défini remplace les variables par des espaces réservés spécifiques, puis transmet les valeurs des variables pour les remplir et les restituer lors du rendu réel.
Pourquoi se donner tant de mal ? Ne serait-il pas agréable d'utiliser directement la méthode query
démontrée précédemment pour effectuer des opérations d'ajout, de suppression, de modification et de recherche ? Eh bien, parlons des avantages des instructions préparées, ou des raisons pour lesquelles nous devrions utiliser des instructions préparées pour l'interaction avec la base de données :
Pour résumer, du point de vue des performances et de la sécurité, il est recommandé d'utiliser des instructions préparées pour gérer les opérations d'ajout, de suppression, de modification et d'interrogation dans la base de données.
Ensuite, nous implémentons les opérations d'ajout, de suppression, de modification et d'interrogation de la base de données MySQL sur la base de l'API d'instruction préparée fournie par PDO. implémentez-le via une approche orientée objet :
<?php class Post { public $id; public $title; public $content; public $created_at; /** * @var PDO */ protected $pdo; public function __construct(PDO $pdo = null) { if ($pdo != null) { $this->pdo = $pdo; } } public function insert($title, $content) { $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)'; try { // 准备预处理语句 $stmt = $this->pdo->prepare($sql); // 获取当前时间对应的格式化字符串:2020-05-28 13:00:00 $datetime = date('Y-m-d H:i:s', time()); // 绑定参数值 $stmt->bindParam(':title', $title, PDO::PARAM_STR); $stmt->bindParam(':content', $content, PDO::PARAM_STR); $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR); // 执行语句 $stmt->execute(); return $this->pdo->lastInsertId(); // 返回插入记录对应ID } catch (PDOException $e) { printf("数据库插入失败: %s\n", $e->getMessage()); } } public function select($id) { $sql = 'SELECT * FROM `post` WHERE id = ?'; try { // 准备预处理语句 $stmt = $this->pdo->prepare($sql); // 绑定参数值 $stmt->bindValue(1, $id, PDO::PARAM_INT); // 执行语句 $stmt->execute(); return $stmt->fetchObject(self::class); // 以对象方式返回结果集 } catch (PDOException $e) { printf("数据库查询失败: %s\n", $e->getMessage()); } } public function selectAll() { $sql = 'SELECT * FROM `post` ORDER BY id DESC'; try { // 准备预处理语句 $stmt = $this->pdo->prepare($sql); // 执行语句 $stmt->execute(); return $stmt->fetchAll(); // 返回所有结果集 } catch (PDOException $e) { printf("数据库查询失败: %s\n", $e->getMessage()); } } public function update($id) { $sql = 'UPDATE `post` SET created_at = :created_at WHERE id = :id'; try { // 准备预处理语句 $stmt = $this->pdo->prepare($sql); $datetime = date('Y-m-d H:i:s', time()); // 绑定参数值 $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR); $stmt->bindValue(':id', $id, PDO::PARAM_INT); // 执行语句 $stmt->execute(); return $stmt->rowCount(); } catch (PDOException $e) { printf("数据库更新失败: %s\n", $e->getMessage()); } } public function delete($id) { $sql = 'DELETE FROM `post` WHERE id = ?'; try { // 准备预处理语句 $stmt = $this->pdo->prepare($sql); // 绑定参数值 $stmt->bindValue(1, $id, PDO::PARAM_INT); // 执行语句 $stmt->execute(); return $stmt->rowCount(); } catch (PDOException $e) { printf("数据库删除失败: %s\n", $e->getMessage()); } } }
Nous avons construit une classe Post
, puis initialisé l'instance $pdo
dans le constructeur (transmise de l'extérieur), puis décomposé l'ajout, la suppression, opérations de modification et d'interrogation basées sur des instructions préparées dans les méthodes de classe correspondantes. La logique globale est très simple.Prenons insert
comme exemple.Tout d'abord, le modèle SQL est transmis via la méthode prepare de l'objet PDO pour construire l'instruction préparée.Cette méthode renvoie ensuite l'objet PDOStatement. l'objet est appelé pour lier la valeur du paramètre spécifique, le premier paramètre de cette méthode est l'espace réservé, le deuxième paramètre est la valeur du paramètre et le troisième paramètre est le type de valeur (les constantes correspondantes peuvent être interrogées dans les constantes prédéfinies du PDO) .Après avoir lié les paramètres, vous pouvez appeler la méthode d'exécution de l'objet PDOStatement pour exécuter l'instruction préparée.
Pour les opérations d'insertion, vous pouvez utiliser la méthode lastInsertId sur l'objet PDO pour renvoyer l'ID de clé primaire de l'enregistrement inséré. Pour les méthodes de mise à jour et de suppression, vous pouvez utiliser la méthode rowCount sur l'objet PDOStatement pour renvoyer l'ID de clé primaire de l'enregistrement inséré. nombre de lignes affectées pour indiquer si l’opération a réussi. Pour les opérations de requête, un seul enregistrement peut être renvoyé via la méthode fetch de l'objet PDOStatement, ou une instance d'objet mappée à une classe spécifiée (également un seul enregistrement) peut être renvoyée via la méthode fetchObject. Pour plusieurs résultats, elle peut être renvoyée. via la méthode fetchAll.
Il convient de noter que lors de la déclaration d'instructions préparées, vous pouvez utiliser l'espace réservé ?
ou un espace réservé plus lisible tel que :name
, puis lier Lors du passage des paramètres, vous pouvez transmettre soit la valeur de liaison, soit la valeur de liaison. Méthode bindParam. Les paramètres passés dans les deux méthodes sont les mêmes, sauf que pour l'espace réservé ?
, vous devez établir un mappage avec le modèle SQL via le numéro de séquence numérique (en commençant par 1).
Il n'est pas difficile de comprendre le code ci-dessus en combinant le code et la documentation officielle PHP. Ensuite, écrivons le code de test :
// 初始化 PDO 连接实例 $dsn = 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4'; $user = 'root'; $pass = 'root'; try { $pdo = new PDO($dsn, $user, $pass); } catch (PDOException $e) { printf("数据库连接失败: %s\n", $e->getMessage()); } // 测试代码 $post = new Post($pdo); // insert $title = '这是一篇测试文章'; $content = '测试内容: 今天天气不错'; $id = $post->insert($title, $content); echo '文章插入成功: ' . $id . '<br>'; // select $item = $post->select($id); echo '<pre class="brush:php;toolbar:false">'; print_r($item); // update $affected = $post->update($id); echo '受影响的行数: ' . $affected . '<br>'; // delete $affected = $post->delete($id); echo '受影响的行数: ' . $affected . '<br>'; // selectAll $items = $post->selectAll(); print_r($items);
Initialisez une instance d'objet PDO et transmettez-la dans le Post
return $stmt->fetchAll(PDO::FETCH_CLASS, self::class);
public function batchInsert(array $items) { $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)'; try { // 开启事务 $this->pdo->beginTransaction(); // 准备预处理语句 $stmt = $this->pdo->prepare($sql); foreach ($items as $item) { // 绑定参数值 $datetime = date('Y-m-d H:i:s', time()); $stmt->bindParam(':title', $item->title, PDO::PARAM_STR); $stmt->bindParam(':content', $item->content, PDO::PARAM_STR); $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR); // 执行语句 $stmt->execute(); } $this->pdo->commit(); // 提交事务 return $stmt->rowCount(); // 返回受影响的行数 } catch (PDOException $e) { $this->pdo->rollBack(); // 回滚事务 printf("数据库批量插入失败: %s\n", $e->getMessage()); } }
fetchAll
Post
contient par défaut à la fois le mappage d'index et le champ mappage de noms. , cela peut être résolu en définissant le mode d'acquisition. Par exemple, si vous souhaitez renvoyer un tableau de
objets, vous pouvez faire ceci :$post = new Post($pdo); $items = [ [ 'title' => '这是一篇测试文章111', 'content' => '测试内容' ], [ 'title' => '这是一篇测试文章222', 'content' => '测试内容' ], [ 'title' => '这是一篇测试文章333', 'content' => '测试内容' ], ]; $post->batchInsert($items); $items = $post->selectAll(); print_r($items);
Post
Transaction de base de donnéesbatchInsert
public function batchInsert(array $items) { $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)'; try { // 开启事务 $this->pdo->beginTransaction(); // 准备预处理语句 $stmt = $this->pdo->prepare($sql); foreach ($items as $item) { // 绑定参数值 $datetime = date('Y-m-d H:i:s', time()); $stmt->bindParam(':title', $item->title, PDO::PARAM_STR); $stmt->bindParam(':content', $item->content, PDO::PARAM_STR); $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR); // 执行语句 $stmt->execute(); } $this->pdo->commit(); // 提交事务 return $stmt->rowCount(); // 返回受影响的行数 } catch (PDOException $e) { $this->pdo->rollBack(); // 回滚事务 printf("数据库批量插入失败: %s\n", $e->getMessage()); } }
我们只需要在执行 SQL 序列之前调用 PDO 对象的 beginTransaction 方法开启事务,然后在所有 SQL 语句执行完成后调用 commit 方法提交事务,如果 SQL 执行过程中出错,则在异常处理代码中通过 PDO 对象的 rollBack 方法回滚事务。
为上述方法编写测试代码:
$post = new Post($pdo); $items = [ [ 'title' => '这是一篇测试文章111', 'content' => '测试内容' ], [ 'title' => '这是一篇测试文章222', 'content' => '测试内容' ], [ 'title' => '这是一篇测试文章333', 'content' => '测试内容' ], ]; $post->batchInsert($items); $items = $post->selectAll(); print_r($items);
执行这段代码,打印结果中包含新插入的文章数据,则表明事务提交成功:
关于通过 PDO 扩展与 MySQL 数据库交互,我们就简单介绍到这里,更多细节可以阅读官方文档,相信通过这几个课程的学习,你已经对 MySQL 数据库的基本使用以及如何在 PHP 中连接数据库并进行增删改查有了初步的认知,从下篇教程开始,我们将结合具体实战项目来开发一个现代的 PHP 项目,将之前的学习到的知识点应用到实战中,并且引入一些现代的 PHP 理念对项目进行管理。
想了解更多相关文章,敬请关注php mysql栏目!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!