A. php如何获得 pdo 查询结果 列名
回调函数。
1.快取一行
FetchColumn是为应用程序取得一个仅包含单列的数据,代码如下:
$u = $db->query(“SELECT id FROM users WHERE login=
‘login’ AND password=‘password’”);
fetch(PDO::FETCH_COLUMN)
if ($u->fetchColumn()) { //返回一个字符串
//登录成功
} else {
//验证失败
}
?>
2.取得一个标准对象
还可以将取得的一行作为一个标准类stdClass的对象实例,其中列名=属性名。
$res = $db->query(“SELECT * FROM foo”);
while ($obj = $res->fetch(PDO::FETCH_OBJ)) {
// $obj == instance of stdClass
}
?>
3.存取为一个类
PDO允许将结果保存为一个类,例子如下:
$res = $db->query(“SELECT * FROM foo”);
$res->setFetchMode(
PDO::FETCH_CLASS,
“className”,
array(‘optional’=‘Constructor Params’)
);
while ($obj = $res->fetch()) {
// $obj == instance of className
}
?>
4.从一个类取得常量
PDO允许查询的结果可以被用来生成一个目的类。
$res = $db->query(“SELECT * FROM foo”);
$res->setFetchMode(
PDO::FETCH_CLASS |
PDO::FETCH_CLASSTYPE
);
while ($obj = $res->fetch()) {
// $obj == instance of class who’s name is
// found in the value of the 1st column
}
?>
5.存取为一个对象
PDO还允许获取数据到一个已经存在的对象。
$u = new userObject;
$res = $db->query(“SELECT * FROM users”);
$res->setFetchMode(PDO::FETCH_INTO, $u);
while ($res->fetch()) {
// 取得的记录集将放在$u这个对象变量中,在此显示
}
?>
6.存取为关联数据
PDO实现了迭代器(Iteator)接口,允许一个方法实现迭代的功能。
$res = $db->query(
“SELECT * FROM users”,
PDO::FETCH_ASSOC
);
foreach ($res as $row) {
// $row是一个关联数组,可以直接显示,如$row['id']
}
?>
7.fetchAll()方法
PDO也提供了和ADODB类似的fetchAll()方法,它允许从一个结果集中取得数据,然后放于关联数组中。
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
$qry = “SELECT * FROM users”;
$res = $db->query($qry)->fetchAll(PDO::FETCH_ASSOC);
?>
或者获取到索引数组里:
$res = $db->query("SELECT * FROM foo");
$result_arr = $res->fetchAll();
print_r($result_arr);
?>
数字索引数组比较浪费资源,请尽量使用关联数组,这样可以在内存中使用相当密集的大型结果集。
相关说明如下:
setAttribute()方法用于设置部分属性,主要属性有:PDO::ATTR_CASE、PDO::ATTR_ERRMODE等,这里需要设置的是PDO::ATTR_CASE,就是使用关联索引获取数据集时,关联索引是大写还是小写,有如下几个选择:
PDO::CASE_LOWER——强制列名是小写;
PDO::CASE_NATURAL——列名按照原始的方式;
PDO::CASE_UPPER——强制列名为大写。
我们使用setFetchMode方法来设置获取结果集的返回值的数据类型,类型有:
PDO::FETCH_ASSOC——关联数组形式;
PDO::FETCH_NUM——数字索引数组形式;
PDO::FETCH_BOTH——两种数组形式都有,这是默认的;
PDO::FETCH_OBJ——按照对象的形式,类似于以前的 mysql_fetch_object()。
当然,一般情况下,我们使用PDO::FETCH_ASSOC取得关联数组。具体使用哪种类型,应按照自己的实际应用选择。
8.fetchColumn()方法
如果想获取指定记录里的一个字段结果,则可以使用PDOStatement::fetchColumn()。
$rs = $db->query("SELECT COUNT(*) FROM foo");
$col = $rs->fetchColumn();
echo $col;
?>
一般使用fetchColumn()方法进行count统计,对某些只需要单字段的记录可以很好地操作。
9.回调函数
PDO还规定在每一个fetch模式下,经过处理后的结果中使用一个回调函数。
function draw_message($subject,$email) { … }
$res = $db->query(“SELECT * FROM msg”);
$res->fetchAll(PDO::FETCH_FUNC,“draw_message”);
?>
10.直接查询的问题
直接使用Query查询行每次都会直接提交给数据库,如果查询较多,每次频频查询将导致效率降低。
另外,在安全问题上,没有过滤一些特殊字符容易产生SQL注入。
11.过滤字符
下面我们来看看如何使用PDO进行过滤引起SQL注入的方法,即过滤特殊字符。我们在PDO中使用quote()方法,使用例子如下:
$query = “SELECT * FROM users WHERE
login=“.$db->quote($_POST[‘login’]).”
AND
passwd=“.$db->quote($_POST[‘pass’]);
12.事务处理
PDO驱动程序支持所有的事务数据库,并且PDO提供更简便的方法,如下:
$db->beginTransaction();
if ($db->exec($qry) === FALSE) {
$db->rollback();
}
$db->commit();
?>
13.执行一个批处理事务
在下面的示例中,假设我们为一个新雇员创建一组条目,这个雇员有一个ID号,即23。除了输入这个雇员的基本数据外,还需要记录雇员的薪水。分别完成两个更新很简单,但通过将这两个更新包括在beginTransaction()和commit()调用中,就可以保证在更改完成之前,其他人无法看到更改。如果发生了错误,catch块可以回滚事务开始以来发生的所有更改,并打印出一条错误消息。代码内容如下:
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO_ATTR_PERSISTENT => true));
echo "Connected\n";
$dbh->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last)
values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
?>
B. 我的php里面有php_pdo.dll,打开网页还是出这个错:Fatal error: Class 'PDO' not found in
你前面引用这个类所在的文件了么?
include_once("PDO.php");
并不是存在PDO.dll就可以使用的,那只是PHP环境支持你调用了
类还需要自己写或者引入
C. PHP的PDO使用:
引入smarty.class.php类没有
$pdo = new PDO("mysql:host=localhost;dbname=newsdb;charset=utf8","root","root");
最好定义一下字符集
D. PHP 的 pdo 方法,怎么返回字段名
PDO是PDO, Mysqli是Mysqli,我们没办法要求PDO像Mysqli保持一样的结构和设计。
也许你会觉得mysqli的fetch_field很方便,但是实际上这个方法的使用概率极低,因为通常会读出表的所有字段信息并缓存起来,而不是总是进行字段查询。
表现最明显的框架如Cakephp,当你用直接编辑数据表的方法增加了一个新字段之后数据并不会被保存到这个字段中,必须先清除缓存的数据表信息才行。
通过阅读不同的PHP框架,我们可以发现极少会有框架需要开发人员直接调用PDO或者mysqli对象去执行sql,它们往往将其通过DbAdapter之类的接口进行封装。我建议你思考这样做的好处然后优化自己的代码结构。你问题中的这个行为通常也不需要封装在db对象中,一般是在Table对象处理,例如
class Table {
protected $_tableName;
public function __construct($tableName);
protected function _readFieldsPrototype();
protected function _getCachedFieldsPrototype();
public function getFieldPrototype($filed);
}
E. 为什么 PHP 应该使用 PDO 方式访问数据库
很多程序员都学习过如何使用 MySQL 或 MySQLi 扩展访问数据库。在 PHP 5.1 中,有一个更好的方法。PHP Data Objects(PDO) 提供了很多预处理语句的方法,且使用对象将使你的工作更有成效!
PDO 介绍
“PDO – PHP Data Objects – 是一个对多种数据库提供统一操作方法的数据库访问层。”
它并不具备数据库特有的语法,但它将使切换数据库和平台更加容易,多数情况下,只需要简单修改链接字符串。
这并非一篇完整教导如何使用SQL的教程。它重要为那些现今仍在使用 mysql 或 mysqli 扩展的人,帮助他们跃至更具可移植性和强力的 PDO。
数据库支持
此扩展可以使用 PDO 驱动编写过的所有数据库。在本文书写时,下面的数据库支持已经实现:
PDO_DBLIB ( FreeTDS / Microsoft SQL Server / Sybase )
PDO_FIREBIRD ( Firebird/Interbase 6 )
PDO_IBM ( IBM DB2 )
PDO_INFORMIX ( IBM Informix Dynamic Server )
PDO_MYSQL ( MySQL 3.x/4.x/5.x )
PDO_OCI ( Oracle Call Interface )
PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC and win32 ODBC) )
PDO_PGSQL ( PostgreSQL )
PDO_SQLITE ( SQLite 3 and SQLite 2 )
PDO_4D ( 4D )
你的系统不会也不必支持所有上面的驱动;下面是一个快速检查所支持数据库的方法:
1 print_r(PDO::getAvailableDrivers());
连接
不同数据库的连接方法可能稍有不同,下面是一些较为流行的数据库连接方法。你将注意到,虽然数据库类型不同,前三种数据库的连接方式是相同的——而 SQLite 使用自己的语法。
Connection String
01 try {
02 # MS SQL Server andSybase with PDO_DBLIB
03 $DBH = newPDO("mssql:host=$host;dbname=$dbname, $user, $pass");
04 $DBH = newPDO("sybase:host=$host;dbname=$dbname, $user, $pass");
05
06 # MySQL with PDO_MYSQL
07 $DBH = newPDO("mysql:host=$host;dbname=$dbname", $user, $pass);
08
09 # SQLite Database
10 $DBH = newPDO("sqlite:my/database/path/database.db");
11 }
12 catch(PDOException $e) {
13 echo$e->getMessage();
14 }
注意 try/catch 块——你应该总是使用 try/catch 包装你的 PDO 操作,并使用异常机制——这里只是简单的示例。通常,你只需要一个连接——有很多可以教你语法的列表。 $DBH 代表“数据库句柄”,这将贯穿全文。
通过将句柄设置为 NULL,你可以关闭任一连接。
1 # close the connection
2 $DBH = null;
你可以在PHP.net找到更多数据库特定选项和/或其它数据库连接字符串的信息。
异常与 PDO
PDO 可以使用异常处理错误,这意味着你的所有 PDO 操作都应当包装在一个 try/catch 块中。你可以通过设定错误模式属性强制 PDO 在新建的句柄中使用三种错误模式中的某一个。下面是语法:
1 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
2 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
3 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
无论你设定哪个错误模式,一个错误的连接总会产生一个异常,因此创建连接应该总是包装在 try/catch 块中。
PDO::ERRMODE_SILENT
这是默认的错误模式。如果你使用这个模式,你将得使用同 mysql 或 mysqli 扩展一样的方法差错。其它两种模式更适合 DRY 编程。
PDO::ERRMODE_WARNING
此方法将会发出一个标准PHP警告,并允许程序继续运行。这对调试很有帮助。
PDO::ERRMODE_EXCEPTION
这是多数情况下你所希望的方式。它生成异常,允许你更容易的处理错误,隐藏可能导致它人了解你系统的信息。下面是一个充分利用异常的示例:
01 # connect to the database
02 try {
03 $DBH = newPDO("mysql:host=$host;dbname=$dbname", $user, $pass);
04 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
05
06 # UH-OH! Typed DELECT instead of SELECT!
07 $DBH->prepare('DELECT name FROM people');
08 }
09 catch(PDOException $e) {
10 echo"I'm sorry, Dave. I'm afraid I can't do that.";
11 file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
12 }
在 select 语句中有一个故意留下的错误;这将导致一个异常。异常错误细节保存至一个 log 文件,并生成一段友好的(或不怎么友好的)信息于用户。
插入和更新
插入新数据,更新已存数据是一种非常常见的数据库操作。使用 PDO,这通常需要两个步骤。本节中所述的所有内容对更新和插入都有效。
这里有一个最基本的插入示例:
1 # STH means "Statement Handle"
2 $STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
3 $STH->execute();
你也可以使用 exec() 完成相同的操作,这将减少调用。多数情况下,你会使用调用多的方法,以充分利用语句预处理的优势。即使你只用它一次,使用语句预处理,帮助你保护你的 SQL 免于注入攻击。
预处理语句
使用语句预处理将帮助你免于SQL注入攻击。
一条预处理语句是一条预编译的 SQL 语句,它可以使用多次,每次只需将数据传至服务器。其额外优势在于可以对使用占位符的数据进行安全处理,防止SQL注入攻击。
你通过在 SQL 语句中使用占位符的方法使用预处理语句。下面是三个例子:一个没有占位符,一个使用无名占位符,一个使用命名占位符。
1 # no placeholders - ripe for SQL Injection!
2 $STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");
3
4 # unnamed placeholders
5 $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
6
7 # named placeholders
8 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
你希望避免第一种方法。选择命名我无名占位符将会对你对语句中数据的设置产生影响。
无名占位符
01 # assign variables to each place holder, indexed 1-3
02 $STH->bindParam(1, $name);
03 $STH->bindParam(2, $addr);
04 $STH->bindParam(3, $city);
05
06 # insert one row
07 $name = "Daniel"
08 $addr = "1 Wicked Way";
09 $city = "Arlington Heights";
10 $STH->execute();
11
12 # insert another row with different values
13 $name = "Steve"
14 $addr = "5 Circle Drive";
15 $city = "Schaumburg";
16 $STH->execute();
这里有两步。首先,我们对各个占位符指定变量(2-4行)。然后,我们对各个占位符指定数据,并执行语句。要发送另一组数据,只需改变这些变量的值并再次执行语句。
这种方法看上去对拥有很多参数的语句很笨拙吧?的确。然而,当数据保存于数组中时,这非常容易简略:
1 # the data we want to insert
2 $data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');
3
4 $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
5 $STH->execute($data);
容易吧!
数组中的数据按顺序填入占位符中。 $data[0]是第一个,$data[1]是第二个,依次。不过,要是数组中数据的次序不正确,这将不能正常运行,你需要先对数组排序。
命名占位符
你可能已经开始猜测语法了,不过下面就是示例:
1 # the first argument is the named placeholder name - notice named
2 # placeholders always start with a colon.
3 $STH->bindParam(':name', $name);
你可以看使用快捷方式,但它需使用关联数组。下面是示例:
1 # the data we want to insert
2 $data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );
3
4 # the shortcut!
5 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
6 $STH->execute($data);
数组中的键不需要以冒号开头,但其它部分需要同占位符匹配。如果你有一个二维数组,你只需遍历它,并对遍历的每个数组执行语句。
命名占位符的另一个好的功能是直接将对象插入到你的数据库中,只要属性同命名字段匹配。下面是一个示例对象,以及如何将它插入到数据库中的示例:
01 # a simple object
02 class person {
03 public $name;
04 public $addr;
05 public $city;
06
07 function __construct($n,$a,$c) {
08 $this->name = $n;
09 $this->addr = $a;
10 $this->city = $c;
11 }
12 # etc ...
13 }
14
15 $cathy = new person('Cathy','9 Dark and Twisty','Cardiff');
16
17 # here's the fun part:
18 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
19 $STH->execute((array)$cathy);
通过在执行时将对象转换为数组,输将将会同数组的键一样对待。
F. php连接数据库关于PDO类和PDOStatement类的区别是什么
这代表两个不同的对象,看一下PDO::query()的定义:
public PDOStatement PDO::query ( string $statement )
可以知道query返回的结果是PDOStatement实例对象,那么你至少可以知道PDOStatement可以用来操作结果集了。
看一下PDOStatement类有哪些方法:
http://php.net/manual/zh/class.pdostatement.php
发现有fetch,fetchAll等熟悉的功能,不是么?
然后再来看看PDO::prepare()方法
public PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] )
它也是返回的PDOStatement,按照手册的说法,PDOStatement代表一条预处理语句,并在该语句被执行后代表一个相关的结果集。
也就是说,如果你通过PDO::query()直接查询,那么返回的PDOStatement就表示一个结果集。
如果你通过PDO::prepare()查询,实际上并未执行sql,而是得到一个预处理语句(PDOStatement),然后你调用PDOStatement::execute()方法真正执行。