批改状态:合格
老师批语:
实例演示常用 的CURD操作,特别是各种常用组合,如fetch+while…
PDO预处理
预处理的本质是sql语句的动态绑定
动态绑定就是执行时才绑定真实数据SELECT * FROM `表名` WHERE `id` > ?
静态绑定,数据直接写到SQL语句中SELECT * FROM `表名` WHERE `id` > 1
namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//匿名参数:?$sql = 'INSERT `staff` SET `name` = ?, `gender` = ?, `email` = ?;';$stmt = $db->prepare($sql);//SQL语句中占位符“?”,用索引数组绑定真实数据$data = ['admin', 0, 'admin@php.cn'];$stmt->execute($data);echo '<hr>';//打印SQL预处理命令$stmt->debugDumpParams();echo '<br>'.$stmt->errorCode().'<br>';print_r($stmt->errorInfo());echo '<br>id = '.$db->lastInsertId().'<br>';

namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//命名参数:“:xxxx”不用和前面一一对应$sql = 'INSERT `staff` SET `name` = :xname, `gender` = :pgender, `email` = :demail;';$stmt = $db->prepare($sql);//SQL语句中占位符“:xxxx”,用关联数组绑定真实数据// $data = [':xname' => 'admin', ':pgender' => 0, ':demail' => 'admin@php.cn'];//去掉冒号也是可以的$data = ['xname' => 'admin1', 'pgender' => 1, 'demail' => 'admin1@php.cn'];$stmt->execute($data);echo '<hr>';//打印SQL预处理命令$stmt->debugDumpParams();echo '<br>'.$stmt->errorCode().'<br>';print_r($stmt->errorInfo());echo '<br>id = '.$db->lastInsertId().'<br>';

“匿名参数+索引数组”和“命名参数+关联数组”用哪个好?
用哪个都可以,看个人喜好。
/*** 为什么要单独设置参数,而不是在execute()时传参?* execute()默认参数都是字符类型* 通常数字型字符写入数据表时,会转换成正确类型,不会有问题。* 但在分页操作时,会导致错误。* 在参数绑定时,强制类型限制,就很有必要。*/namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//匿名参数:?$sql = 'INSERT `staff` SET `name` = ?, `gender` = ?, `email` = ?;';$stmt = $db->prepare($sql);//bindValue()值绑定,静态绑定,所有参数有确定值。// bindValue(key, value, type),匿名占位符,索引从1开始。// $stmt->bindValue(1, 'admin3', PDO::PARAM_STR);// $stmt->bindValue(2, 0, PDO::PARAM_INT);// $stmt->bindValue(3, 'admin3@php.cn', PDO::PARAM_STR);// 上面是写死的,更灵活应该用数组传参。list($name, $gender, $email) = ['admin4', 1, 'admin4@php.cn'];$stmt->bindValue(1, $name, PDO::PARAM_STR);$stmt->bindValue(2, $gender, PDO::PARAM_INT);$stmt->bindValue(3, $email, PDO::PARAM_STR);list($name, $gender, $email) = ['admin5', 0, 'admin5@php.cn'];$stmt->bindValue(1, $name, PDO::PARAM_STR);$stmt->bindValue(2, $gender, PDO::PARAM_INT);$stmt->bindValue(3, $email, PDO::PARAM_STR);$stmt->execute();echo '<hr>';//打印SQL预处理命令$stmt->debugDumpParams();echo '<br>'.$stmt->errorCode().'<br>';print_r($stmt->errorInfo());echo '<br>id = '.$db->lastInsertId().'<br>';
每插入一条就得绑定一次,也不方便灵活。
namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//heredoc$sql = <<<SQLINSERT `staff`SET `name` = ?, `gender` = ?, `email` = ?;SQL;$stmt = $db->prepare($sql);// 引用绑定$stmt->bindParam(1, $name, PDO::PARAM_STR);$stmt->bindParam(2, $gender, PDO::PARAM_INT);$stmt->bindParam(3, $email, PDO::PARAM_STR);// list($name, $gender, $email) = ['admin6', 1, 'admin6@php.cn'];// $stmt->execute();// echo '<hr>';// 在增加两条条// list($name, $gender, $email) = ['admin7', 0, 'admin7@php.cn'];// $stmt->execute();// echo '<hr>';// list($name, $gender, $email) = ['admin8', 1, 'admin8@php.cn'];// $stmt->execute();// echo '<hr>';// $stmt->execute();// echo '<hr>';// //打印SQL预处理命令// $stmt->debugDumpParams();// echo '<br>'.$stmt->errorCode().'<br>';// print_r($stmt->errorInfo());// echo '<br>id = '.$db->lastInsertId().'<br>';// 用循环和二维数组添加多条$data = [['admin9', 0, 'admin9@php.cn'],['admin10', 1, 'admin10@php.cn'],['admin11', 0, 'admin11@php.cn'],];foreach($data as list($name, $gender, $email)){$stmt->execute();echo '<hr>';//打印SQL预处理命令$stmt->debugDumpParams();echo '<br>'.$stmt->errorCode().'<br>';print_r($stmt->errorInfo());echo '<br>id = '.$db->lastInsertId().'<br>';}
namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//heredoc$sql = <<<SQLINSERT `staff` SET `name` = ?, `gender` = ?, `email` = ?;SQL;$stmt = $db->prepare($sql);//注释“引用绑定”,引起错误// $stmt->bindParam(1, $name, PDO::PARAM_STR);// $stmt->bindParam(2, $gender, PDO::PARAM_INT);// $stmt->bindParam(3, $email, PDO::PARAM_STR);$data = [['admin12', 0, 'admin12@php.cn'],//['admin13', 0, 'admin13@php.cn'],];foreach($data as list($name, $gender, $email)){if($stmt->execute()){if($stmt->rowCount() > 0){echo 'sql执行成功,id ='.$db->lastInsertId().'<br>';echo '<hr>';}else{echo '执行失败';print_r($stmt->errorInfo());}}else{echo 'sql执行失败';print_r($stmt->errorInfo());}}

Tips
- else:应用于开发调试阶段,生产环境中应将错误信息集中写到日志文件中。
- sql执行失败很常见,通常是语法错误,例如字段名写错等。
- 新增失败通常是权限问题,如没有插入权限或者当前表被锁定只读等,磁盘满也有可能。
namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//heredoc$sql = <<<SQLUPDATE `staff` SET `name` = ?, `gender` = ?, `email` = ?WHERE `id`= ?;SQL;// !!!!最高提示:禁止无条件更新,生产环境必须杜绝。// stripos()忽略大小写if (false === stripos($sql, 'where')){exit('禁止无条件更新!');}$stmt = $db->prepare($sql);$stmt->bindParam(1, $name, PDO::PARAM_STR);$stmt->bindParam(2, $gender, PDO::PARAM_INT);$stmt->bindParam(3, $email, PDO::PARAM_STR);$stmt->bindParam(4, $id, PDO::PARAM_INT);$data = [['admin8', 0, 'admin8@php.cn', 8],];foreach($data as list($name, $gender, $email, $id)){if($stmt->execute()){if($stmt->rowCount() > 0){echo '成功更新了'.$stmt->rowCount().'条记录<br>';echo '<hr>';}else{echo '更新重复:没有记录被更新!<br>';print_r($stmt->errorInfo());$stmt->debugDumpParams();}}else{echo 'sql执行失败';print_r($stmt->errorInfo());}}
成功时,
重复的更新将被拦截,
....//不写条件WHERE测试$sql = <<<SQLUPDATE `staff` SET `name` = ?, `gender` = ?, `email` = ?;SQL;// 最高提示:禁止无条件更新,生产环境必须杜绝。// stripos()忽略大小写if (false === stripos($sql, 'where')){exit('禁止无条件更新!');}....

namespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//heredoc$sql = <<<SQLDELETE FROM `staff`WHERE `id`= ?;SQL;// 最高提示:禁止无条件删除,生产环境必须杜绝。// stripos()忽略大小写if (false === stripos($sql, 'where')){exit('禁止无条件删除!');}$stmt = $db->prepare($sql);$stmt->bindParam(1, $id, PDO::PARAM_INT);$data = [[11],[10],];foreach($data as list($id)){echo $id.'<br>';if($stmt->execute()){if($stmt->rowCount() > 0){echo '成功删除了'.$stmt->rowCount().'条记录<br>';echo '<hr>';}else{echo '重复删除:没有记录被删除!<br>';print_r($stmt->errorInfo());// $stmt->debugDumpParams();}}else{echo 'sql执行失败';print_r($stmt->errorInfo());}}
// 查询 fetch + whilenamespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//heredoc$sql = <<<SQLSELECT `id`, `name`, `email` FROM `staff`LIMIT ?;SQL;$stmt = $db->prepare($sql);// $num = 5;// $stmt->bindParam(1, $num, PDO::PARAM_INT);$stmt->bindValue(1, 5, PDO::PARAM_INT);if($stmt->execute()){// fetch()逐条获取,指针自动后移指向下一条,失败返回false,成功返回记录。// $staff = $stmt->fetch(PDO::FETCH_ASSOC);// if($staff)// {// printf('<pre>%s</pre><br>',print_r($staff, true));// }else// {// echo '没有查询到数据!<br>';// }while($staff = $stmt->fetch(PDO::FETCH_ASSOC)){printf('<pre>%s</pre><br>',print_r($staff, true));}}else{echo 'sql执行失败';print_r($stmt->errorInfo());$stmt->debugDumpParams();}

// 查询 fetchallnamespace pdo_edu;use PDO;$db = new PDO('mysql:dbname=phpedu', 'phpedu', 'phpedu');//heredoc$sql = <<<SQLSELECT `id`, `name`, `email` FROM `staff`LIMIT ?;SQL;$stmt = $db->prepare($sql);// $num = 5;// $stmt->bindParam(1, $num, PDO::PARAM_INT);$stmt->bindValue(1, 4, PDO::PARAM_INT);if($stmt->execute()){// fetchall()获取全部记录。while($staffs = $stmt->fetchAll(PDO::FETCH_ASSOC)){foreach($staffs as$staff){printf('<pre>%s</pre><br>',print_r($staff, true));}}}else{echo 'sql执行失败';print_r($stmt->errorInfo());$stmt->debugDumpParams();}

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号