获取单个对象
要从查询结果创建单个对象,有两种方法。
1.使用熟悉的fetch()方法:
class user {};$stmt = $pdo->query('select name from users limit 1');$stmt->setfetchmode(pdo::fetch_class, 'user');$user = $stmt->fetch();
2.专用的fetchobject()方法:
class user {};$user = $pdo->query('select name from users limit 1')->fetchobject('user');
虽然这两个代码段都将为你提供相同的user类实例,
/* object(user)#3 (1) { ["name"] => string(4) "john"} */
后一种方法看起来绝对更简洁。此外,如果使用了fetch()方法,但是没有使用这样的名称定义类,则将静默返回一个数组,而使用fetchobject()将抛出一个适当的错误。
获取对象数组
当然,上面描述的两种方法都可以与一个熟悉的while语句一起使用,从数据库中获取结果行。
使用一个方便的fetchall()方法一次获取对象数组中所有返回的记录:
class user {};$users = $pdo->query('select name from users')->fetchall(pdo::fetch_class, 'user');
将给你一个数组,由一个user类的对象组成,返回数据填充属性:
/* array(2) { [0]=> object(user)#3 (1) { ["name"] => string(4) "john" } [1]=> object(user)#4 (1) { ["name"]=> string(4) "mike" }} */
注意,你可以将此模式与pdo::fetch_unique和pdo::fetch_group组合使用,以获得由唯一字段索引的结果数组,或者分别使用非唯一字段对结果进行分组。
例如,下面的代码将返回一个数组,其中记录id将用作数组索引而不是连续数字。
class user {};$stmt = $pdo->query('select id, id, name, car from users');$users = ->fetchall(pdo::fetch_class|pdo::fetch_unique, 'user');
分配类属性
无论选择哪种方法,查询返回的所有列都将按照以下规则分配给对应的类属性:
1.如果有一个类属性,它的名称与列名相同,则将为该属性分配列值
2.如果没有这样的属性,那么将调用一个魔术方法__set()
3.如果没有为该类定义__set()方法,那么将创建一个公共属性并为其分配一个列值。
例如,这段代码
class user{ public $name;}$user = $pdo->query('select * from users limit 1')->fetchobject('user');
将给你一个对象,所有属性自动分配,无论它们是否存在于类中:
/* object(user)#3 (4) { ["id"] => string(3) "104" ["name"] => string(4) "john" ["sex"] => string(4) "male" ["car"] => string(6) "toyota"} */
从这一点可以看出,为了避免自动创建属性,你可以使用魔术方法__set()过滤掉属性。最简单的过滤技术就是一个空的__set()方法。使用它,只会设置现有的属性:
class user{ private $name; public function __set($name, $value) {}}$user = $pdo->query('select * from users limit 1')->fetchobject('user');/*array(1) { [0]=> object(user)#3 (1) { ["name":"user":private]=> string(4) "john" }} */
如上pdo还可以为私有属性分配值。
将构造函数参数传递给对象
当然,对于新创建的对象,我们可能需要提供构造函数参数。为此,fetchobject()和fetchall()方法都有一个专用的参数,你可以使用它以数组的形式传递构造函数参数。
假设我们有一个类user,它有一个car属性,可以通过提供的变量在构造函数中设置:
class user { public function __construct($car) { $this->car = $car; }}
在获取记录时,我们应该添加一个带有构造函数参数的数组:
$users = $pdo->query('select name from users limit 1') ->fetchall(pdo::fetch_class, 'user', ['caterpillar']);$user = $pdo->query('select name from users limit 1') ->fetchobject('user',['caterpillar']);
/* object(user)#3 (2) { ["name"] => string(4) "john" ["car"] => string(11) "caterpillar"} */
可以看到,数据库中的值被覆盖了,因为默认情况下pdo在调用构造函数之前分配类属性。这可能是一个问题,但很容易解决:
在调用构造函数后设置类属性
mysql_fetch_object()注释:
如果你使用mysql_fetch_object并指定一个类——属性将在构造函数执行之前设置。这通常不是问题,但是如果你的属性是通过__set()魔术方法设置的,那必须首先执行构造函数逻辑,否则可能会导致一些主要问题。
可惜mysql是一个mysqli扩展,但我们使用的是pdo。因此,有一种方法可以告诉pdo在构造函数执行之后分配属性。为此,必须使用pdo::fetch_props_late常量。
使用fetchall()将非常简单,
class user { public function __construct($car) { $this->car = $car; }}$stmt = $pdo->query('select name, car from users limit 1');$users = $stmt->fetchall(pdo::fetch_class|pdo::fetch_props_late, 'user', ['caterpillar']);
在获取单个行时,我们需要同时调用setfetchmode()和fetchobject(),这可能有点不方便。
class user { public function __construct($car) { $this->car = $car; }}$stmt = $pdo->query('select name, car from users limit 1');$stmt->setfetchmode(pdo::fetch_class|pdo::fetch_props_late, 'user');$user = $stmt->fetchobject('user', ['caterpillar']);/*object(user)#3 (2) { ["car"] => string(6) "toyota" ["name"] => string(4) "john"} */
如上这段代码效率并不高,因为我们必须编写两次类名。
或者,我们可以使用fetch():
$stmt = $pdo->query('select name, car from users limit 1');$stmt->setfetchmode(pdo::fetch_class|pdo::fetch_props_late, 'user', ['caterpillar']);$user = $stmt->fetch();
但是,如上所述,如果一个类恰好是未定义的,它将无法帮助我们处理错误消息。
从数据库中获取类名
还有一个更有趣的标志,它告诉pdo从第一列的值中获取类名。使用这个标志,可以避免使用setfetchmode()和fetch():
$data = $pdo->query("select 'user', name from users") ->fetch(pdo::fetch_class | pdo::fetch_classtype);/*object(user)#3 (1) { ["name"]=> string(4) "john"} */
此外,如果可以从同一个查询创建不同类的对象,那么这种模式将非常有用
class male {};class female {};$stmt = $pdo->query('select sex, name from users');$users = $stmt->fetchall(pdo::fetch_class | pdo::fetch_classtype);/*array(6) { [0]=> object(male)#3 (1) { ["name"]=> string(4) "john" } [1]=> object(male)#4 (1) { ["name"]=> string(4) "mike" } [2]=> object(female)#5 (1) { ["name"]=> string(4) "mary" } [3]=> object(female)#6 (1) { ["name"]=> string(5) "kathy" }}*/
然而,当使用这种模式时,似乎不可能在类构造函数中传递任何参数。
更新现有对象
除了创建新对象,pdo还可以更新现有对象。只使用setfetchmode(),它将现有变量作为参数。显然,使用fetchall()是无用的。
class user{ public $name; public $state; public function __construct() { $this->name = null; }}$user = new user;$user->state = "up'n'running";var_dump($user);$stmt = $pdo->query('select name from users limit 1');$stmt->setfetchmode(pdo::fetch_into, $user);$data = $stmt->fetch();var_dump($data, $user);/*object(foo)#2 (2) { ["name"] => null ["state"] => string(12) "up'n'running"}object(foo)#2 (2) { ["name"] => string(4) "john" ["state"] => string(12) "up'n'running"}object(foo)#2 (2) { ["name"] => string(4) "john" ["state"] => string(12) "up'n'running"} */
如上,fetch()调用返回的是相同的对象,这在我看来是多余的。还要注意,与pdo::fetch_class不同,这种模式不分配私有属性。
以上就是如何获取pdo对象并设置属性?(代码详解)的详细内容。
