Selecting Data
你在mysql_*中是这样做的
1 <?php
2 $result = mysql_query('SELECT * from table') or die(mysql_error());
3
4 $num_rows = mysql_num_rows($result);
5
6 while($row = mysql_fetch_assoc($result)) {
7 echo $row['field1'];
8 }
你在pdo中可以这个样
<?php
$stmt = $db->query('SELECT * FROM table');
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['field1'];
}
或者
<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)) {
echo $row['field1'];
}
提示:如果你使用了方法像query()。这个方法返回一个PDOStatement 对象,如果你想取出结果,请这样使用:
<?php
foreach($db->query('SELECT * FROM table') as $row) {
echo $row['field1'];
}
PDO数据是通过->fetch() 方法获得的,这个方法是你的statement处理的。
在fetch之前。最好告诉PDO这个数据你打算怎么fetch。在下个章节我会解释。
Fetch Modes
PDO::FETCH_ASSOC 可以在fetch() 和 fetchAll()中使用。 这个告诉PDO返回关联数组,字段的名字作为key。这还有很多fench方法。
首先我说明怎么选择fench 模式。
$stmt->fetch(PDO::FETCH_ASSOC)
在这里我用的是fetch,你也可以用:
- PDOStatement::fetchAll() 返回了一个数组包含了所有选择的行
- PDOStatement::fetchColumn() 返回下一行的一列作为结果集
- PDOStatement::fetchObject() 返回下一行作为一个对象
- PDOStatement::setFetchMode() 设置fetch模式
下面讨论fetch模式
- PDO::FETCH_ASSOC 关联数组
- PDO::FETCH_BOTH 默认的。返回关联数组和索引数组。
还有更多选项,可以阅读文档。
获取行的数量
不是通过mysql_num_rows 而是通过rowCount(),比如说:
<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
获取插入的id
<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();
Insert and Update or Delete statements
在mysql_*中我们是这样做的
<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);
在PDO中,同样可以这样:
<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;
在上面的语句中,执行了一个sql语句并且返回受影响的行数。
上面的方法在你查询语句中没有变量时很好用。如果有变量,就应该使用 prepared statement or parameterized statement 。
Prepared Statements
Q:什么是 Prepared Statements,我为什么要用他?
A:Prepared Statement 是一条预编译的sql语句,可以被执行多次。
典型的使用Prepared Statement 工作流:
- Prepare: 语句(statement)模版被application创建,发送到数据库管理系统(DBMS)。某些值仍然违背置顶,通过参数、占位符进行绑定
INSERT INTO PRODUCT (name, price) VALUES (?, ?)
DBMS进行解析、编译,得到最优的语句,把结果(语句)储存起来,并不执行。
执行。过后,程序为参数提供或绑定值,DBMS执行语句(一般会返回一个结果)。程序或许会执行多次因为它有不同的值,想获得不同的结果。咱这个例子里,把Bread作为第一个参数,1.00作为第二个参数。
你可以通过引入占位符使用预编译语句。
Q:什么是命名占位符(named placeholders ),怎么使用呢?
A:命名占位符,用过一个冒号而不是? 这样就不用去操心问号的顺序问题了
$stmt->bindParam(':bla', $bla);
<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
另一个对于OOP(面向对象编程)很友好的就是,命名占位符可以直接插入到你的对象,再然后加入到你的数据库。假设属性与字段相同
class person {
public $name;
public $add;
function __construct($a,$b) {
$this->name = $a;
$this->add = $b;
}
}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);
Q:好了,什么是匿名占位符(unnamed placeholders),怎么使用?
A:看个例子。
<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->execute(array('john', '29 bla district'));
注意:在匿名占位符我们一定要注意在数组中的顺序,在PDOStatement::execute() 方法中。
SELECT, INSERT, UPDATE, DELETE prepared queries
- select
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
- insert
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
- delete
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
- update
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();
注意:
PDO和Mysqli也不是完全的安全。有机会会翻译一遍这个文章,这里就简单说一下:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));
下面是一个封装的类
1 class CPdo{
2 protected $_dsn = "mysql:host=localhost;dbname=test";
3 protected $_name = "root";
4 protected $_pass = "";
5 protected $_condition = array();
6 protected $pdo;
7 protected $fetchAll;
8 protected $query;
9 protected $result;
10 protected $num;
11 protected $mode;
12 protected $prepare;
13 protected $row;
14 protected $fetchAction;
15 protected $beginTransaction;
16 protected $rollback;
17 protected $commit;
18 protected $char;
19 private static $get_mode;
20 private static $get_fetch_action;
21 /**
22 *pdo construct
23 */
24 public function __construct($pconnect = false) {
25 $this->_condition = array(PDO::ATTR_PERSISTENT => $pconnect);
26 $this->pdo_connect();
27 }
28 /**
29 *pdo connect
30 */
31 private function pdo_connect() {
32 try{
33 $this->pdo = new PDO($this->_dsn,$this->_name,$this->_pass,$this->_condition);
34 }
35 catch(Exception $e) {
36 return $this->setExceptionError($e->getMessage(), $e->getline, $e->getFile);
37 }
38 }
39 /**
40 *self sql get value action
41 */
42 public function getValueBySelfCreateSql($sql, $fetchAction = "assoc",$mode = null) {
43 $this->fetchAction = $this->fetchAction($fetchAction);
44 $this->result = $this->setAttribute($sql, $this->fetchAction, $mode);
45 $this->AllValue = $this->result->fetchAll();
46 return $this->AllValue;
47 }
48 /**
49 *select condition can query
50 */
51 private function setAttribute($sql, $fetchAction, $mode) {
52 $this->mode = self::getMode($mode);
53 $this->fetchAction = self::fetchAction($fetchAction);
54 $this->pdo->setAttribute(PDO::ATTR_CASE, $this->mode);
55 $this->query = $this->base_query($sql);
56 $this->query->setFetchMode($this->fetchAction);
57 return $this->query;
58 }
59 /**
60 *get mode action
61 */
62 private static function getMode($get_style){
63 switch($get_style) {
64 case null:
65 self::$get_mode = PDO::CASE_NATURAL;
66 break;
67 case true:
68 self::$get_mode = PDO::CASE_UPPER;
69 break;
70 case false;
71 self::$get_mode= PDO::CASE_LOWER;
72 break;
73 }
74 return self::$get_mode;
75 }
76 /**
77 *fetch value action
78 */
79 private static function fetchAction($fetchAction) {
80 switch($fetchAction) {
81 case "assoc":
82 self::$get_fetch_action = PDO::FETCH_ASSOC; //asso array
83 break;
84 case "num":
85 self::$get_fetch_action = PDO::FETCH_NUM; //num array
86 break;
87 case "object":
88 self::$get_fetch_action = PDO::FETCH_OBJ; //object array
89 break;
90 case "both":
91 self::$get_fetch_action = PDO::FETCH_BOTH; //assoc array and num array
92 break;
93 default:
94 self::$get_fetch_action = PDO::FETCH_ASSOC;
95 break;
96 }
97 return self::$get_fetch_action;
98 }
99 /**
100 *get total num action
101 */
102 public function rowCount($sql) {
103 $this->result = $this->base_query($sql);
104 $this->num = $this->result->rowCount();
105 return $this->num;
106 }
107 /*
108 *simple query and easy query action
109 */
110 public function query($table, $column = "*",$condition = array(), $group = "",$order = "", $having = "", $startSet = "",$endSet = "",$fetchAction = "assoc",$params = null){
111 $sql = "select ".$column." from `".$table."` ";
112 if ($condition != null) {
113 foreach($condition as $key=>$value) {
114 $where .= "$key = '$value' and ";
115 }
116 $sql .= "where $where";
117 $sql .= "1 = 1 ";
118 }
119 if ($group != "") {
120 $sql .= "group by ".$group." ";
121 }
122 if ($order != "") {
123 $sql .= " order by ".$order." ";
124 }
125 if ($having != "") {
126 $sql .= "having '$having' ";
127 }
128 if ($startSet != "" && $endSet != "" && is_numeric($endSet) && is_numeric($startSet)) {
129 $sql .= "limit $startSet,$endSet";
130 }
131 $this->result = $this->getValueBySelfCreateSql($sql, $fetchAction, $params);
132 return $this->result;
133 }
134 /**
135 *execute delete update insert and so on action
136 */
137 public function exec($sql) {
138 $this->result = $this->pdo->exec($sql);
139 $substr = substr($sql, 0 ,6);
140 if ($this->result) {
141 return $this->successful($substr);
142 } else {
143 return $this->fail($substr);
144 }
145 }
146 /**
147 *prepare action
148 */
149 public function prepare($sql) {
150 $this->prepare = $this->pdo->prepare($sql);
151 $this->setChars();
152 $this->prepare->execute();
153 while($this->rowz = $this->prepare->fetch()) {
154 return $this->row;
155 }
156 }
157 /**
158 *USE transaction
159 */
160 public function transaction($sql) {
161 $this->begin();
162 $this->result = $this->pdo->exec($sql);
163 if ($this->result) {
164 $this->commit();
165 } else {
166 $this->rollback();
167 }
168 }
169 /**
170 *start transaction
171 */
172 private function begin() {
173 $this->beginTransaction = $this->pdo->beginTransaction();
174 return $this->beginTransaction;
175 }
176 /**
177 *commit transaction
178 */
179 private function commit() {
180 $this->commit = $this->pdo->commit();
181 return $this->commit;
182 }
183 /**
184 *rollback transaction
185 */
186 private function rollback() {
187 $this->rollback = $this->pdo->rollback();
188 return $this->rollback;
189 }
190 /**
191 *base query
192 */
193 private function base_query($sql) {
194 $this->setChars();
195 $this->query = $this->pdo->query($sql);
196 return $this->query;
197 }
198 /**
199 *set chars
200 */
201 private function setChars() {
202 $this->char = $this->pdo->query("SET NAMES 'UTF8'");
203 return $this->char;
204 }
205 /**
206 *process sucessful action
207 */
208 private function successful($params){
209 return "The ".$params." action is successful";
210 }
211 /**
212 *process fail action
213 */
214 private function fail($params){
215 return "The ".$params." action is fail";
216 }
217 /***进程异常动作
218 *process exception action
219 */
220 private function setExceptionError($getMessage, $getLine ,$getFile) {
221 echo "Error message is ".$getMessage."<br /> The Error in ".$getLine." line <br /> This file dir on ".$getFile;
222 exit();
223 }
224 }
封装类2
1 <?php
2 /**
3 */
4
5 //使用pdo连接数据库 封装增删改查
6
7 class DB{
8
9 //定义私有属性
10 private $host;
11 private $port;
12 private $username;
13 private $password;
14 private $dbname;
15 private $charset;
16 private $dbtype;
17 private $pdo;
18
19 //定义构造函数自动加载配置文件
20 function __construct(){
21 //加载配置文件
22 include_once('./config/config.php');
23
24 //给属性赋值
25 $this->dbtype = $config['db'];
26 $this->host = $config['host'];
27 $this->username = $config['username'];
28 $this->password = $config['password'];
29 $this->charset = $config['charset'];
30 $this->port = $config['port'];
31 $this->dbname = $config['dbname'];
32
33 //pdo连接数据库
34 $this->pdo = new PDO("$this->dbtype:host=$this->host;dbname=$this->dbname","$this->username","$this->password");
35 //发送编码
36 $this->pdo->query("set names $this->charset");
37 }
38
39 /**
40 * 定义执行查询sql语句的方法
41 * 参数: 查询sql语句
42 * 返回: 二维关联数组
43 */
44 public function query($sql){
45 $res = $this->pdo->query($sql);
46 $res->setFetchMode(PDO::FETCH_ASSOC);
47 $arr = $res->fetchAll();
48 return $arr;
49 }
50
51
52 /**
53 * 查询一行记录的方法
54 * 参数:表名 条件(不包含where)
55 * 返回:一维关联数组
56 */
57 public function getRow($tablename,$where){
58 //组装sql语句
59 $sql = "select * from $tablename where $where";
60 //查询
61 $res = $this->pdo->query($sql);
62 $res->setFetchMode(PDO::FETCH_ASSOC);
63 $arr = $res->fetch();
64 return $arr;
65 }
66
67
68 /**
69 * 查询全部记录
70 * 参数:表名
71 * 返回:二维关联数组
72 */
73 public function getAll($tablename){
74 $res = $this->pdo->query("select * from $tablename");
75 $res->setFetchMode(PDO::FETCH_ASSOC);
76 $arr = $res->fetchAll();
77 return $arr;
78 }
79
80 /**
81 * 查询某个字段
82 * 参数: 字段名(多个的话用逗号隔开) 表名 条件(不含where)
83 * 返回: 二维关联数组
84 */
85 public function getOne($column,$tablename,$where="1"){
86 //拼接sql语句
87 $sql = "select $column from $tablename where $where";
88 $rs = $this->pdo->query($sql);
89 $rs->setFetchMode(PDO::FETCH_ASSOC);
90 //$col = $rs->fetchColumn();
91 $col = $rs->fetchAll();
92 return $col;
93 }
94
95
96 /**
97 * 查询最后一次插入的数据
98 * 参数:表名
99 * 返回:数组
100 */
101 public function getlastone($tablename){
102 $sql = "select * from $tablename where id=(select max(id) from $tablename)";
103 $res = $this->pdo->query($sql);
104 $res->setFetchMode(PDO::FETCH_ASSOC);
105 $arr = $res->fetch();
106 return $arr;
107 }
108
109
110 /**
111 * 向数据库中添加一条信息
112 * 参数:表名 一维关联数组
113 * 返回: 布尔值
114 */
115 public function insert($tablename,$arr){
116 //拿到数组之后先处理数组 过滤字段
117 //取出表中的字段
118 $sql = "select COLUMN_NAME from information_schema.COLUMNS where table_name = '$tablename' and table_schema ='$this->dbname'";
119 $columns = $this->pdo->query($sql);
120 $columns->setFetchMode(PDO::FETCH_ASSOC);
121 $columns = $columns->fetchAll();
122 $cols = array(); //存储表中的全部字段
123 foreach($columns as $key=>$val){
124 $cols[] = $val['COLUMN_NAME'];
125 }
126 //将要入库的数组进行键值分离
127 $keys = array();
128 $values = '';
129 foreach($arr as $k=>$v){
130 if(!in_array($k,$cols)){
131 unset($arr[$k]);
132 }else{
133 $keys[] = $k;
134 $values .= "'".$v."',";
135 }
136 }
137 $column = implode(',',$keys);
138 $values = substr($values,0,-1);
139 //拼接sql语句
140 $sql = "insert into $tablename($column) values ($values)";
141 $res = $this->pdo->exec($sql);
142 return $res;
143 }
144
145
146 /**
147 * 删除数据 其实就是改变字段值使之不被查询
148 * 参数:表名 条件(不含where)
149 * 返回:布尔
150 */
151 public function delete($tablename,$where){
152 $sql = "update $tablename set is_del=1 where $where";
153 $res = $this->pdo->exec($sql);
154 return $res;
155 }
156
157
158 /**
159 * 修改数据
160 * 参数:表名 要修改的数据的数组
161 * 返回:布尔
162 */
163 public function update($tablename,$arr,$where){
164 //处理传过来的数组
165 $str = "";
166 foreach($arras $k=>$v){
167 $str .= "$k='".$v."',";
168 }
169 //截取字符串
170 $str = substr($str,0,-1);
171 //拼接sql语句
172 $sql = "update $tablename set $str where $where";
173 $res = $this->pdo->exec($sql);
174 return $res;
175 }
176 }