<?php declare(strict_types=1); ini_set('display_errors', 'On'); ini_set('error_reporting', E_ALL); $driver = 'mysql'; // 数据库驱动 $host = 'localhost'; // 主机地址 $dbname = 'test_db'; // 数据库名 $port = 3306; // 服务端口号 $charset = 'utf8mb4'; // 字符编码 $username = 'zhangsan'; // 账号 $password = '********'; // 密码 // 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服务端) PDO::ATTR_STRINGIFY_FETCHES => false, // 若为true则所有int字段都会以string类型返回,在使用===判等时务必注意 ]; // 构造数据源名称(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' => 3]; 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) { if ($row['sex'] === 1) { $sex = '男'; } elseif ($row['sex'] === 2) { $sex = '女'; } else { $sex = '保密'; } echo "俺叫{$row['name']}($sex),出生于{$row['birth']}年。" . PHP_EOL; // 俺叫张三(男),出生于2003年。 } // 模糊查询示例 $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 © 2025 码农人生. All Rights Reserved