参见 PDO::FETCH_ORI_* 游标常量的游标常量。
| 获取模式 | 摘要 |
|---|---|
PDO::FETCH_DEFAULT
|
用于当前默认获取模式的特殊值。 |
PDO::FETCH_ASSOC
|
仅按列名索引的数组。 |
PDO::FETCH_BOTH(默认)
|
同时按列号和列名索引的数组。 |
PDO::FETCH_NAMED
|
保留重复列的 PDO::FETCH_ASSOC 变体。
|
PDO::FETCH_NUM
|
仅按列号索引的数组。 |
PDO::FETCH_COLUMN
|
单列。 |
PDO::FETCH_KEY_PAIR
|
键值对,按第一列索引。 |
PDO::FETCH_FUNC
|
使用函数创建返回值。(仅适用于 PDOStatement::fetchAll()) |
PDO::FETCH_OBJ
|
匿名(stdClass)对象。 |
PDO::FETCH_CLASS
|
指定类的对象。 |
这些模式用于在使用 PDO::FETCH_CLASS 时实现选项。
| 获取模式 | 摘要 |
|---|---|
PDO::FETCH_CLASSTYPE
|
使用第一列作为类名。 |
PDO::FETCH_PROPS_LATE
|
在设置属性之前调用构造方法。 |
PDO::FETCH_SERIALIZE
|
使用 PHP 序列化数据。自 PHP 8.1.0 起弃用。 |
以下模式无法与 PDOStatement::fetchAll() 一起使用。
| 获取模式 | 摘要 |
|---|---|
PDO::FETCH_BOUND
|
将值绑定到指定变量。 |
PDO::FETCH_INTO
|
更新现有对象。 |
PDO::FETCH_LAZY
|
通过 PDORow 实现延迟获取,以支持类似数组和对象的访问方式。 |
以下适用于多结果的特殊模式仅与 PDOStatement::fetchAll() 兼容,且不适用于某些其他获取模式。详情请参阅完整文档。
| 获取模式 | 摘要 |
|---|---|
PDO::FETCH_GROUP
|
结果按第一列分组。 |
PDO::FETCH_UNIQUE
|
结果按第一列(唯一)索引。 |
结果中可能包含使用相同名称的多个列。例如,在连接两个表时,这两个表都包含具有相同名称的列。
由于 PHP 的数组和对象等结构不支持使用相同名称的多个 key 或属性,返回的数组或对象将仅包含其中一个使用相同名称的值。
对于重复名称,指定返回哪个值应视为未定义行为。
为避免此问题,可以使用别名手动命名列。例如:
SELECT table1.created_at AS t1_created_at,
table2.created_at AS t2_created_at
FROM table1
JOIN table2 ON table1.table2id = table2.id
参见 PDO::FETCH_NAMED、PDO::ATTR_FETCH_TABLE_NAMES 和
PDO::ATTR_FETCH_CATALOG_NAMES。
可以使用 PDO::__construct() 或 PDO::setAttribute(),通过
PDO::ATTR_DEFAULT_FETCH_MODE 设置所有查询的默认获取模式。
可以使用 PDOStatement::setFetchMode() 为特定语句设置默认获取模式。这会影响作为预处理语句的再次使用以及迭代(使用 foreach)。
PDOStatement::setAttribute() 无法用于设置默认获取模式。它仅接受特定驱动程序的属性,并会静默忽略未识别的属性。
自 PHP 8.0.7 起可用。
这是一个特殊值,PDOStatement 是当前默认使用的获取模式。当扩展 PDOStatement 以与
PDO::ATTR_STATEMENT_CLASS 一起使用时,它作为方法参数的默认值非常有用。
此值不能与 PDO::ATTR_DEFAULT_FETCH_MODE 一起使用。
PDO::FETCH_ASSOC 返回仅按列名索引的数组。
<?php
$stmt = $pdo->query("SELECT userid, name, country FROM users");
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
print_r($row);以上示例会输出:
Array
(
[userid] => 104
[name] => Chris
[country] => Ukraine
)
这是默认的获取模式。
PDO::FETCH_BOTH 返回同时列号和列名索引的数组。这意味着每一行结果中的每个返回值都是重复的。
列号从 0 开始,由查询结果中的列顺序决定,而不是表中定义的列顺序。
注意: 不建议使用数字列索引,因为当查询发生更改时,或者在使用
SELECT *时表结构发生更改,列索引可能会发生变化。
注意: 在多个返回列使用相同名称的情况下,按名称索引的条目数量可能与按数字索引的条目数量不匹配。
<?php
$stmt = $pdo->query("SELECT userid, name, country FROM users");
$row = $stmt->fetch(\PDO::FETCH_BOTH);
print_r($row);以上示例会输出:
Array
(
[id] => 104,
[0] => 104,
[name] => Chris,
[1] => Chris,
[country] => Ukraine,
[2] => Ukraine
)
PDO::FETCH_NAMED 返回的结果格式与
PDO::FETCH_ASSOC 相同,但当多个列使用相同名称时,所有值将以列表形式返回。
有关重复列名的处理及其替代方法的更多信息,请参阅上文关于重复名称处理的部分。
重复值的返回顺序应视为未定义。无法确定每个值的来源。
<?php
$stmt = $pdo->query(
"SELECT users.*, referrer.name
FROM users
LEFT JOIN users AS referrer ON users.referred_by = referrer.userid
WHERE userid = 109"
);
$row = $stmt->fetch(\PDO::FETCH_NUM);
print_r($row);以上示例会输出:
Array
(
[userid] => 109
[name] => Array
(
[0] => Toni
[1] => Chris
)
[country] => Germany
[referred_by] = 104
)
PDO::FETCH_NUM 返回的数组仅按列号索引。列号从 0
开始,并由查询中的结果列顺序决定,而不是(例如)表中定义的列顺序。
注意: 不建议使用数字列索引,因为当查询发生更改时,或者在使用
SELECT *时表结构发生更改,该索引可能会发生变化。
<?php
$stmt = $pdo->query("SELECT userid, name, country FROM users");
$row = $stmt->fetch(\PDO::FETCH_NUM);
print_r($row);以上示例会输出:
Array
(
[0] => 104
[1] => Chris
[2] => Ukraine
)
PDO::FETCH_COLUMN 用于返回单列的值。可通过 PDOStatement::setFetchMode()
或 PDOStatement::fetchAll() 的第二个参数指定要返回的列。
若指定的列不存在,将抛出 ValueError。
<?php
$stmt = $pdo->query("SELECT name, country FROM users LIMIT 3");
$row = $stmt->fetchAll(\PDO::FETCH_COLUMN);
print_r($row);
$stmt = $pdo->query("SELECT name, country FROM users LIMIT 3");
$row = $stmt->fetchAll(\PDO::FETCH_COLUMN, 1);
print_r($row);以上示例会输出:
Array
(
[0] => Chris
[1] => Jamie
[2] => Robin
)
Array
(
[0] => Ukraine
[1] => England
[2] => Germany
)
PDO::FETCH_KEY_PAIR 返回以第一列为索引的键值对,结果必须仅包含两列。此获取模式仅适用于
PDOStatement::fetchAll()。
注意: 若第一列不唯一,将丢失部分值,具体哪些值会丢失属于未定义行为。
<?php
$stmt = $pdo->query("SELECT name, country FROM users LIMIT 3");
$row = $stmt->fetchAll(\PDO::FETCH_KEY_PAIR);
print_r($row);以上示例会输出:
Array
(
[Chris] => Ukraine
[Jamie] => England
[Robin] => Germany
)
指定用于创建返回值的函数。此模式仅可用于 PDOStatement::fetchAll()。
该函数以各列的值作为参数接收。因无法获知某个值原本关联的列名,因此必须确保查询中的列顺序与函数参数顺序一致。
注意:
PDO::FETCH_GROUP和PDO::FETCH_UNIQUE的效果会在调用该函数之前应用于结果。
<?php
function valueCreator($col1, $col2, $col3)
{
return [
'col1' => $col1,
'col2' => strtoupper($col2),
'col3' => $col3,
'customKey' => 'customValue',
];
}
$stmt = $pdo->query("SELECT userid, name, country FROM users LIMIT 3");
$row = $stmt->fetchAll(\PDO::FETCH_FUNC, valueCreator(...));
print_r($row);以上示例会输出:
Array
(
[0] => Array
(
[col1] => 104
[col2] => SAM
[col3] => Ukraine
[customKey] => customValue
)
[1] => Array
(
[col1] => 105
[col2] => JAMIE
[col3] => England
[customKey] => customValue
)
[2] => Array
(
[col1] => 107
[col2] => ROBIN
[col3] => Germany
[customKey] => customValue
)
)
PDO::FETCH_OBJ 返回 stdClass 对象。
参见 PDOStatement::fetchObject() 和
PDO::FETCH_CLASS。
<?php
$stmt = $pdo->query("SELECT userid, name, country FROM users");
$row = $stmt->fetch(\PDO::FETCH_OBJ);
print_r($row);以上示例会输出:
stdClass Object
(
[userid] => 104
[name] => Chris
[country] => Ukraine
)
返回指定类的对象。有关附加行为,请参见选项 flag。
如果返回的列名与对象中已存在的属性名称不匹配,将会动态声明该属性。已废弃此行为,并自 PHP 9.0 起会引发错误。
参见 PDOStatement::fetchObject()。
<?php
class TestEntity
{
public $userid;
public $name;
public $country;
public $referred_by_userid;
public function __construct()
{
print "Constructor called with ". count(func_get_args()) ." args\n";
print "Properties set when constructor called? "
. (isset($this->name) ? 'Yes' : 'No') . "\n";
}
}
$stmt = $db->query(
"SELECT userid, name, country, referred_by_userid FROM users"
);
$stmt->setFetchMode(PDO::FETCH_CLASS, TestEntity::class);
$result = $stmt->fetch();
var_dump($result);以上示例的输出类似于:
Constructor called with 0 args
Properties set when constructor called? Yes
object(TestEntity)#3 (4) {
["userid"]=>
int(104)
["name"]=>
string(5) "Chris"
["country"]=>
string(7) "Ukraine"
["referred_by_userid"]=>
NULL
}
此获取模式仅可与 PDO::FETCH_CLASS(及其他选项)结合使用。
使用此获取模式时,PDO 会将返回结果的第一列作为要实例化的类名。
若指定的类未找到,将返回 stdClass 对象,且不产生警告或错误。
<?php
class TestEntity
{
public $userid;
public $name;
public $country;
public $referred_by_userid;
public function __construct()
{
print "Constructor called with ". count(func_get_args()) ." args\n";
print "Properties set when constructor called? "
. (isset($this->name) ? 'Yes' : 'No') . "\n";
}
}
$stmt = $db->query(
"SELECT 'TestEntity', userid, name, country, referred_by_userid FROM users"
);
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
$result = $stmt->fetch();
var_dump($result);以上示例的输出类似于:
Constructor called with 0 args
Properties set when constructor called? Yes
object(TestEntity)#3 (4) {
["userid"]=>
int(104)
["name"]=>
string(5) "Chris"
["country"]=>
string(7) "Ukraine"
["referred_by_userid"]=>
NULL
}
此获取模式仅可与 PDO::FETCH_CLASS(及其他选项)结合使用。
使用此获取模式时,会在属性赋值前调用构造方法。
<?php
class TestEntity
{
public $userid;
public $name;
public $country;
public $referred_by_userid;
public function __construct()
{
print "Constructor called with ". count(func_get_args()) ." args\n";
print "Properties set when constructor called? "
. (isset($this->name) ? 'Yes' : 'No') . "\n";
}
}
$stmt = $db->query(
"SELECT userid, name, country, referred_by_userid FROM users"
);
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, TestEntity::class);
$result = $stmt->fetch();
var_dump($result);以上示例的输出类似于:
Constructor called with 0 args
Properties set when constructor called? No
object(TestEntity)#3 (4) {
["userid"]=>
int(104)
["name"]=>
string(5) "Chris"
["country"]=>
string(7) "Ukraine"
["referred_by_userid"]=>
NULL
}
此功能自 PHP 8.1.0 起弃用。强烈建议不要应用此功能。
此获取模式仅可与 PDO::FETCH_CLASS(及其他选项)结合使用。
使用此获取模式时,指定的类必须实现 Serializable。
此功能不支持包含完整序列化对象(通过 serialize() 生成)的字符串。
此获取模式不会调用构造方法。
<?php
class TestEntity implements Serializable
{
public $userid;
public $name;
public $country;
public $referred_by_userid;
public function __construct()
{
print "Constructor called with " . count(func_get_args()) . " args\n";
print "Properties set when constructor called? "
. (isset($this->name) ? 'Yes' : 'No') . "\n";
}
public function serialize()
{
return join(
"|",
[$this->userid, $this->name, $this->country, $this->referred_by_userid]
);
}
public function unserialize(string $data)
{
$parts = explode("|", $data);
$this->userid = (int) $parts[0];
$this->name = $parts[1];
$this->country = $parts[2];
$refId = $parts[3];
$this->referred_by_userid = ($refId === "" ? null : (int) $refId);
}
}
print "Set up record (constructor called manually):\n";
$db->exec(
"CREATE TABLE serialize (
sdata TEXT
)"
);
$origObj = new TestEntity();
$origObj->userid = 200;
$origObj->name = 'Seri';
$origObj->country = 'Syria';
$origObj->referred_by_userid = null;
$insert = $db->prepare("INSERT INTO serialize (sdata) VALUES (:sdata)");
$insert->execute(['sdata' => $origObj->serialize()]);
print "\nRetrieve result:\n";
$query = "SELECT sdata FROM serialize";
$stmt = $db->query($query);
// NOTE: Constructor is never called!
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_SERIALIZE, TestEntity::class);
$result = $stmt->fetch();
var_dump($result);以上示例的输出类似于:
Deprecated: TestEntity implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in Standard input code on line 2
Set up record (constructor called manually):
Constructor called with 0 args
Properties set when constructor called? No
Retrieve result:
Deprecated: PDOStatement::setFetchMode(): The PDO::FETCH_SERIALIZE mode is deprecated in Standard input code on line 58
Deprecated: PDOStatement::fetch(): The PDO::FETCH_SERIALIZE mode is deprecated in Standard input code on line 59
object(TestEntity)#5 (4) {
["userid"]=>
int(200)
["name"]=>
string(4) "Seri"
["country"]=>
string(5) "Syria"
["referred_by_userid"]=>
NULL
}
此获取模式无法与 PDOStatement::fetchAll() 一起使用。
此获取模式不直接返回结果,而是将值绑定到通过 PDOStatement::bindColumn()
指定的变量,所调用的获取方法返回 true。
注意: 使用预处理语句时,为确保正确运行,变量必须在查询执行后进行绑定。
<?php
$query = "SELECT users.userid, users.name, users.country, referrer.name
FROM users
LEFT JOIN users AS referrer ON users.referred_by_userid = referrer.userid";
$stmt = $db->prepare($query);
$stmt->execute();
$stmt->bindColumn('userid', $userId);
$stmt->bindColumn('name', $name);
$stmt->bindColumn('country', $country);
// Bind by column position to resolve duplicated column name
// To avoid this breaking if the query is changed, use an SQL alias instead
// For example: referrer.name AS referrer_name
$stmt->bindColumn(4, $referrerName);
while ($stmt->fetch(\PDO::FETCH_BOUND)) {
print join("\t", [$userId, $name, $country, ($referrerName ?? 'NULL')]) . "\n";
}以上示例会输出:
104 Chris Ukraine NULL 105 Jamie England NULL 107 Robin Germany Chris 108 Sean Ukraine NULL 109 Toni Germany NULL 110 Toni Germany NULL
This fetch mode cannot be used with PDOStatement::fetchAll().
This fetch mode updates properties in the specified object. The object is returned on success.
If a property does not exist with the name of a returned column, it will be dynamically declared. This behavior is deprecated and will cause an error from PHP 9.0.
Properties must be public and cannot be
readonly.
There's no way to change the object to be updated without using PDOStatement::setFetchMode() between retrieving each record.
<?php
class TestEntity
{
public $userid;
public $name;
public $country;
public $referred_by_userid;
}
$obj = new TestEntity();
$stmt->setFetchMode(\PDO::FETCH_INTO, $obj);
$stmt = $db->query("SELECT userid, name, country, referred_by_userid FROM users");
$result = $stmt->fetch();
var_dump($result);以上示例的输出类似于:
object(TestEntity)#3 (4) {
["userid"]=>
int(104)
["name"]=>
string(5) "Chris"
["country"]=>
string(7) "Ukraine"
["referred_by_userid"]=>
NULL
}
This fetch mode cannot be used with PDOStatement::fetchAll().
This fetch mode returns a PDORow object which provides
both array- and object-like access to values (i.e. combines the behavior of
PDO::FETCH_BOTH and
PDO::FETCH_OBJ), retrieved in a lazy manner.
This can provide memory efficient access (on the PHP side) to unbuffered results on the database server. Whether PDO uses client-side buffering for results depends on the database-specific driver used (and its configuration).
PDORow will return NULL without
any error or warning when accessing properties or keys that are not defined.
This can make errors such as typos or queries not returning expected data
harder to spot and debug.
The returned PDORow object is updated each time a result is retrieved.
<?php
$stmt = $db->query("SELECT userid, name, country, referred_by_userid FROM users");
$result = $stmt->fetch(\PDO::FETCH_LAZY);
print "ID: ". $result[0] ."\n";
print "Name: {$result->name}\n";
print "Country: " . $result['country'] ."\n";
// Returns NULL. No warning or error is raised.
print "Does not exist: " . var_export($result->does_not_exist, true) . "\n";
$differentResult = $stmt->fetch(\PDO::FETCH_LAZY);
// The previously retrieved PDORow now points to the newly retrieved result
print "ID: ". $result[0] ."\n";以上示例会输出:
ID: 104 Name: Chris Country: Ukraine Does not exist: NULL ID: 105
PDO::FETCH_GROUP returns lists of associative arrays,
indexed by a (non-unique) column. This fetch mode only works with
PDOStatement::fetchAll().
When combined with PDO::FETCH_UNIQUE, both modes will
use the same column, rendering the combination of these modes useless.
This fetch should be combined with one of
PDO::FETCH_ASSOC, PDO::FETCH_BOTH,
PDO::FETCH_NAMED, PDO::FETCH_NUM,
PDO::FETCH_COLUMN or
PDO::FETCH_FUNC.
If no fetch mode from the above list is given, the current default fetch mode for the PDOStatement will be used.
<?php
$stmt = $pdo->query("SELECT country, userid, name FROM users");
$row = $stmt->fetchAll(\PDO::FETCH_GROUP | \PDO::FETCH_ASSOC);
print_r($row);以上示例会输出:
Array
(
[Ukraine] => Array
(
[0] => Array
(
[userid] => 104
[name] => Chris
)
[1] => Array
(
[userid] => 108
[name] => Sean
)
)
[England] => Array
(
[0] => Array
(
[userid] => 105
[name] => Jamie
)
)
[Germany] => Array
(
[0] => Array
(
[userid] => 107
[name] => Robin
)
[1] => Array
(
[userid] => 109
[name] => Toni
)
)
)
In the above example one should note that the first column is omitted from the array for each row, only available as the key. It can be included by repeating the column, as in the following example:
<?php
$stmt = $pdo->query("SELECT country, userid, name, country FROM users");
$row = $stmt->fetchAll(\PDO::FETCH_GROUP | \PDO::FETCH_ASSOC);
print_r($row);以上示例会输出:
Array
(
[Ukraine] => Array
(
[0] => Array
(
[userid] => 104
[name] => Chris
[country] => Ukraine
)
[1] => Array
(
[userid] => 108
[name] => Sean
[country] => Ukraine
)
)
[England] => Array
(
[0] => Array
(
[userid] => 105
[name] => Jamie
[country] => England
)
)
[Germany] => Array
(
[0] => Array
(
[userid] => 107
[name] => Robin
[country] => Germany
)
[1] => Array
(
[userid] => 109
[name] => Toni
[country] => Germany
)
)
)
PDO::FETCH_UNIQUE uses the first column to index records,
returning 1 record per index value. This fetch mode only works with
PDOStatement::fetchAll().
When combined with PDO::FETCH_GROUP, both modes will use
the same column, rendering the combination of these modes useless.
This fetch should be combined with one of
PDO::FETCH_ASSOC, PDO::FETCH_BOTH,
PDO::FETCH_NAMED, PDO::FETCH_NUM,
PDO::FETCH_COLUMN or
PDO::FETCH_FUNC.
If no fetch mode from the above list is given, the current default fetch mode for the PDOStatement will be used.
When used with a column that is known to be unique (such as record ID), this mode provides the ability to quickly return results indexed by that value.
注意: If the first column is not unique, values will be lost. Which value(s) are lost should be considered undefined.
Filtering records should be done in SQL where possible. The database will use indexes to optimize this process and return only the required records. Selecting more records than required from the database may significantly increase memory usage and query time for larger result sets.
<?php
$stmt = $pdo->query("SELECT userid, name, country FROM users LIMIT 3");
$row = $stmt->fetchAll(\PDO::FETCH_UNIQUE | \PDO::FETCH_ASSOC);
print_r($row);以上示例会输出:
Array
(
[104] => Array
(
[name] => Chris
[country] => Ukraine
)
[105] => Array
(
[name] => Jamie
[country] => England
)
[107] => Array
(
[name] => Robin
[country] => Germany
)
)
In the above example one should note that the first column is omitted from the array for each row, only available as the key. It can be included by repeating the column, as in the following example:
<?php
$stmt = $pdo->query("SELECT userid, userid, name, country FROM users LIMIT 3");
$row = $stmt->fetchAll(\PDO::FETCH_UNIQUE | \PDO::FETCH_ASSOC);
print_r($row);以上示例会输出:
Array
(
[104] => Array
(
[userid] => 104
[name] => Chris
[country] => Ukraine
)
[105] => Array
(
[userid] => 105
[name] => Jamie
[country] => England
)
[107] => Array
(
[userid] => 107
[name] => Robin
[country] => Germany
)
)