PHP中的官方操作数据库PDO

张开发
2026/6/7 19:17:30 15 分钟阅读
PHP中的官方操作数据库PDO
PHP中的官方操作数据库PDOPDOPHP Data Objects是 PHP 官方推荐的数据库抽象层它支持 MySQL、PostgreSQL、SQLite 等多种数据库提供了预处理语句防 SQL 注入、事务处理等高级特性面向对象风格代码简洁易维护是现代 PHP 开发的首选。开启 PDO 扩展在使用 PDO 前需确认 PHP 环境已开启pdo_mysql扩展。创建phpinfo.php文件?phpphpinfo();?访问页面搜索pdo_mysql若看到PDO Driver for MySQL为enabled则说明已开启。若未开启修改php.ini取消extensionpdo_mysqlWindows或extensionpdo_mysql.soLinux前的注释重启 Web 服务即可。连接 MySQL 数据库PDO 通过DSN数据源名称连接数据库连接时建议设置错误模式为异常、字符集为 utf8mb4这是生产环境的标准配置。newPDO(string$dsn,// DSN 字符串包含主机、数据库名、字符集string$username,// 数据库用户名string$password,// 数据库密码array$options[]// 可选配置数组错误模式、属性等):PDO标准连接?php// 数据库配置$hostlocalhost;$dbnametest_db;$usernameroot;$passwordyour_password;$charsetutf8mb4;// 支持 emoji推荐// DSN 字符串$dsnmysql:host$host;dbname$dbname;charset$charset;// 配置选项设置错误模式为异常设置默认获取方式为关联数组$options[PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION,// 异常模式推荐方便调试PDO::ATTR_DEFAULT_FETCH_MODEPDO::FETCH_ASSOC,// 默认返回关联数组PDO::ATTR_EMULATE_PREPARESfalse,// 禁用模拟预处理使用真实预处理更安全];try{// 连接数据库$pdonewPDO($dsn,$username,$password,$options);echo数据库连接成功;}catch(PDOException$e){// 捕获连接异常die(数据库连接失败.$e-getMessage());}?预处理语句防 SQL 注入SQL 注入是最常见的安全漏洞PDO 的预处理语句是解决这个问题的最佳方案。它的原理是先发送 SQL 模板带占位符再发送参数数据与逻辑完全分离绝对安全。两种占位符PDO 支持两种占位符推荐使用命名占位符更直观命名占位符:name如:username、:age问号占位符?按顺序绑定参数使用预处理查询数据SELECT?php// 假设已连接数据库$pdo 是 PDO 对象// 1. 准备 SQL 模板使用命名占位符$sqlSELECT id, username, email FROM users WHERE age :age AND city :city;// 2. 预处理 SQL$stmt$pdo-prepare($sql);// 3. 绑定参数并执行方式一直接传数组给 execute推荐$params[:age18,:city北京];$stmt-execute($params);// 4. 获取结果// fetch()获取一条数据// fetchAll()获取所有数据$users$stmt-fetchAll();// 遍历结果foreach($usersas$user){echoID: .$user[id]. - 用户名: .$user[username].br;}?使用预处理插入数据INSERT?php// 假设已连接数据库// 1. 准备 SQL$sqlINSERT INTO users (username, email, age) VALUES (:username, :email, :age);$stmt$pdo-prepare($sql);// 2. 绑定参数并执行$params[:username张三,:emailzhangsanexample.com,:age25];$stmt-execute($params);// 3. 获取插入的自增 ID非常常用$newId$pdo-lastInsertId();echo数据插入成功新记录 ID.$newId;?使用预处理更新 / 删除数据UPDATE/DELETE?php// 假设已连接数据库// 更新数据$sqlUPDATE users SET age :age WHERE id :id;$stmt$pdo-prepare($sql);$stmt-execute([:age26,:id1]);// 获取受影响的行数$affectedRows$stmt-rowCount();echo更新成功受影响行数.$affectedRows;// 删除数据同理$sqlDELETE FROM users WHERE id :id;$stmt$pdo-prepare($sql);$stmt-execute([:id10]);echo删除成功受影响行数.$stmt-rowCount();?获取结果的常用方式PDO 提供了多种获取结果的方式通过fetch()或fetchAll()的参数控制模式常量说明PDO::FETCH_ASSOC返回关联数组键名为字段名PDO::FETCH_NUM返回索引数组键名为数字索引PDO::FETCH_OBJ返回对象属性名为字段名PDO::FETCH_COLUMN返回指定列的值配合fetchColumn()?php// 假设已连接数据库$sqlSELECT id, username FROM users LIMIT 2;$stmt$pdo-prepare($sql);$stmt-execute();// 1. 关联数组默认推荐$usersAssoc$stmt-fetchAll(PDO::FETCH_ASSOC);echo关联数组pre;print_r($usersAssoc);echo/pre;// 2. 对象$stmt-execute();// 重新执行重置指针$usersObj$stmt-fetchAll(PDO::FETCH_OBJ);echo对象pre;print_r($usersObj);echo/pre;// 3. 获取单个值比如获取用户总数$sqlSELECT COUNT(*) FROM users;$stmt$pdo-prepare($sql);$stmt-execute();$count$stmt-fetchColumn();// 获取第一列的值echo用户总数.$count;?事务处理保证数据一致性事务用于确保一组 SQL 操作要么全部成功要么全部失败例如转账操作A 扣钱和 B 加钱必须同时成功。PDO 的事务操作非常简洁。方法说明beginTransaction()开启事务关闭自动提交commit()提交事务所有操作生效rollBack()回滚事务所有操作撤销?php// 假设已连接数据库try{// 1. 开启事务$pdo-beginTransaction();// 2. 执行操作 1A 账户扣 100 元$sqlUPDATE accounts SET balance balance - 100 WHERE id 1;$stmt$pdo-prepare($sql);$stmt-execute();if($stmt-rowCount()0){thrownewException(A 账户扣款失败);}// 3. 执行操作 2B 账户加 100 元$sqlUPDATE accounts SET balance balance 100 WHERE id 2;$stmt$pdo-prepare($sql);$stmt-execute();if($stmt-rowCount()0){thrownewException(B 账户加款失败);}// 4. 提交事务$pdo-commit();echo转账成功;}catch(Exception$e){// 5. 回滚事务如果任何一步出错$pdo-rollBack();echo转账失败.$e-getMessage();}?错误处理三种模式PDO 提供了三种错误处理模式推荐使用异常模式PDO::ERRMODE_EXCEPTION因为它能清晰地抛出错误方便调试和处理。模式常量说明PDO::ERRMODE_SILENT静默模式默认不报错只设置错误码PDO::ERRMODE_WARNING警告模式抛出 E_WARNING 警告PDO::ERRMODE_EXCEPTION异常模式抛出 PDOException 异常推荐最佳实践总结永远使用预处理语句这是防 SQL 注入的底线不要拼接 SQL 字符串。设置字符集为 utf8mb4支持 emoji避免中文乱码。使用异常模式PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION方便调试。禁用模拟预处理PDO::ATTR_EMULATE_PREPARES false使用 MySQL 原生预处理更安全。合理使用fetchAll()如果数据量很大比如几万条不要用fetchAll()避免内存溢出应使用fetch()逐行处理。事务处理关键操作涉及多步数据变更如转账、订单时必须使用事务保证一致性。

更多文章