<?php $driver = 'mysql'; // 数据库驱动 $host = 'localhost'; // 主机地址 $dbname = 'test_db'; // 数据库名 $port = 3306; // 服务端口号 $charset = 'utf8mb4'; // 字符编码 $username = 'zhangsan'; // 账号 $password = 'pwd-1234'; // 密码 // PDO连接选项(重要说明:PHP模拟预处理实际上还是拼接SQL,注入问题依旧存在,把预处理工作交给MySQL服务端才可以彻底解决注入问题。) $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset", PDO::ATTR_EMULATE_PREPARES => false, // 禁用PHP模拟预处理(把预处理工作交给MySQL服务端) ]; // 构造数据源名称(Data Source Name)字符串 $dsn = "$driver:"; $dsn .= "host=$host;"; $dsn .= "dbname=$dbname;"; $dsn .= "port=$port;"; $dsn .= "charset=$charset;"; // 创建PDO实例 try { $pdo = new PDO($dsn, $username, $password, $options); } catch (PDOException $e) { exit('创建PDO实例失败:' . $e->getMessage()); } // 构造SQL语句模板 $query = 'SELECT * FROM `prefix_user` WHERE `uid` = :uid LIMIT 1'; // 预处理待执行的SQL语句 try { $sth = $pdo->prepare($query); } catch (PDOException $e) { exit('预处理待执行的SQL语句失败:' . $e->getMessage()); } // 绑定参数 $params = ['uid' => 9527]; foreach ($params as $field => $value) { try { $sth->bindValue(":$field", $value); } catch (PDOException $e) { exit('绑定参数失败:' . $e->getMessage()); } } // 执行SQL $sth->execute(); // 获取查询结果集 $fetchAll = $sth->fetchAll(); $row = $fetchAll[0] ?? []; if ($row) { echo "俺叫{$row['name']}({$row['gender']}),今年{$row['age']}岁。" . PHP_EOL; // 俺叫张三(男),今年18岁。 } // 模糊查询示例 $sth = $pdo->prepare('SELECT * FROM `prefix_article` WHERE `title` LIKE :title LIMIT 1'); $sth->bindValue(':title', '%最好%'); // 查询title字段中包括“最好”的记录 $sth->execute(); $row = $sth->fetchAll()[0] ?? []; if ($row) { echo "{$row['aid']} - {$row['title']}(点击数:{$row['click']})" . PHP_EOL; // 9527 - PHP是世界上最好の语言(点击数:1024) } /** * 修改/mysql/my.cnf文件,设置“general_log = ON”可看到使用PHP模拟预处理和MySQL预处理所执行的SQL是不同的。 * * 使用PHP模拟预处理(PDO::ATTR_EMULATE_PREPARES => true)所执行的SQL * ---------------------------------------------------------------------------------------------------- * Connect zhangsan@localhost on test_db using Socket * Query SET NAMES utf8mb4 * Query SELECT * FROM `prefix_user` WHERE `uid` = '9527' LIMIT 1 * Quit * * 使用MySQL预处理(PDO::ATTR_EMULATE_PREPARES => false)所执行的SQL * ---------------------------------------------------------------------------------------------------- * Connect zhangsan@localhost on test_db using Socket * Query SET NAMES utf8mb4 * Prepare SELECT * FROM `prefix_user` WHERE `uid` = ? LIMIT 1 * Execute SELECT * FROM `prefix_user` WHERE `uid` = '9527' LIMIT 1 * Close stmt * Quit */
Copyright © 2024 码农人生. All Rights Reserved