当前位置:首页 > PHP教程 > php应用 > 列表

如何获取PDO对象并设置属性?(代码详解)

发布:smiling 来源: PHP粉丝网  添加日期:2020-02-03 14:19:18 浏览: 评论:0 

与任何其他数据库扩展一样,PDO可以直接从所选数据创建现有类的实例。但是,与其他扩展不同的是,PDO为强大而灵活的对象操作提供了许多特性。

获取单个对象

要从查询结果创建单个对象,有两种方法。

1.使用熟悉的fetch()方法:

  1. class User {}; 
  2.  
  3. $stmt = $pdo->query('SELECT name FROM users LIMIT 1'); 
  4.  
  5. $stmt->setFetchMode(PDO::FETCH_CLASS, 'User'); 
  6.  
  7. $user = $stmt->fetch(); 

2.专用的fetchObject()方法:

  1. class User {}; 
  2.  
  3. $user = $pdo->query('SELECT name FROM users LIMIT 1')->fetchObject('User'); 

虽然这两个代码段都将为你提供相同的User类实例.

  1. /* object(User)#3 (1) { 
  2.  
  3.   ["name"] => string(4) "John" 
  4.  
  5. } */ 

后一种方法看起来绝对更简洁。此外,如果使用了fetch()方法,但是没有使用这样的名称定义类,则将静默返回一个数组,而使用fetchObject()将抛出一个适当的错误。

获取对象数组

当然,上面描述的两种方法都可以与一个熟悉的while语句一起使用,从数据库中获取结果行。

使用一个方便的fetchAll()方法一次获取对象数组中所有返回的记录:

  1. class User {}; 
  2.  
  3. $users = $pdo->query('SELECT name FROM users')->fetchAll(PDO::FETCH_CLASS, 'User'); 

将给你一个数组,由一个User类的对象组成,返回数据填充属性:

  1. /* array(2) { 
  2.  
  3.   [0]=> object(User)#3 (1) { 
  4.  
  5.     ["name"] => string(4) "John" 
  6.  
  7.   } 
  8.  
  9.   [1]=> object(User)#4 (1) { 
  10.  
  11.     ["name"]=> string(4) "Mike" 
  12.  
  13.   } 
  14.  
  15. } */ 

注意,你可以将此模式与PDO::FETCH_UNIQUE和PDO::FETCH_GROUP组合使用,以获得由唯一字段索引的结果数组,或者分别使用非唯一字段对结果进行分组。

例如,下面的代码将返回一个数组,其中记录id将用作数组索引而不是连续数字。

  1. class User {}; 
  2.  
  3. $stmt  = $pdo->query('SELECT id, id, name, car FROM users'); 
  4.  
  5. $users = ->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_UNIQUE, 'User'); 

分配类属性

无论选择哪种方法,查询返回的所有列都将按照以下规则分配给对应的类属性:

1.如果有一个类属性,它的名称与列名相同,则将为该属性分配列值

2.如果没有这样的属性,那么将调用一个魔术方法__set()

3.如果没有为该类定义__set()方法,那么将创建一个公共属性并为其分配一个列值。

例如,这段代码:

  1. class User 
  2.  
  3.  
  4.     public $name
  5.  
  6.  
  7. $user = $pdo->query('SELECT * FROM users LIMIT 1')->fetchObject('User'); 

将给你一个对象,所有属性自动分配,无论它们是否存在于类中:

  1. /* object(User)#3 (4) { 
  2.  
  3.   ["id"]   => string(3) "104" 
  4.  
  5.   ["name"] => string(4) "John" 
  6.  
  7.   ["sex"]  => string(4) "male" 
  8.  
  9.   ["car"]  => string(6) "Toyota" 
  10.  
  11. } */ 

从这一点可以看出,为了避免自动创建属性,你可以使用魔术方法__set()过滤掉属性。最简单的过滤技术就是一个空的__set()方法。使用它,只会设置现有的属性:

  1. class User 
  2.  
  3.  
  4.     private $name
  5.  
  6.     public function __set($name$value) {} 
  7.  
  8.  
  9. $user = $pdo->query('SELECT * FROM users LIMIT 1')->fetchObject('User'); 
  10.  
  11. /* 
  12.  
  13. array(1) { 
  14.  
  15.   [0]=> object(User)#3 (1) { 
  16.  
  17.     ["name":"User":private]=> string(4) "John" 
  18.  
  19.   } 
  20.  
  21. } */ 

如上PDO还可以为私有属性分配值。

将构造函数参数传递给对象

当然,对于新创建的对象,我们可能需要提供构造函数参数。为此,fetchObject()和fetchAll()方法都有一个专用的参数,你可以使用它以数组的形式传递构造函数参数。

假设我们有一个类User,它有一个car属性,可以通过提供的变量在构造函数中设置:

  1. class User { 
  2.  
  3.     public function __construct($car) { 
  4.  
  5.         $this->car = $car
  6.  
  7.     } 
  8.  

在获取记录时,我们应该添加一个带有构造函数参数的数组:

  1. $users = $pdo->query('SELECT name FROM users LIMIT 1'
  2.  
  3.              ->fetchAll(PDO::FETCH_CLASS, 'User', ['Caterpillar']); 
  4.  
  5.  
  6.  
  7. $user = $pdo->query('SELECT name FROM users LIMIT 1'
  8.  
  9.             ->fetchObject('User',['Caterpillar']); 
  10.  
  11. /* object(User)#3 (2) { 
  12.  
  13.     ["name"] => string(4) "John" 
  14.  
  15.     ["car"]  => string(11) "Caterpillar" 
  16.  
  17. } */ 

可以看到,数据库中的值被覆盖了,因为默认情况下PDO在调用构造函数之前分配类属性。这可能是一个问题,但很容易解决:

在调用构造函数后设置类属性

mysql_fetch_object()注释:

如果你使用mysql_fetch_object并指定一个类——属性将在构造函数执行之前设置。这通常不是问题,但是如果你的属性是通过__set()魔术方法设置的,那必须首先执行构造函数逻辑,否则可能会导致一些主要问题。

可惜mysql是一个mysqli扩展,但我们使用的是PDO。因此,有一种方法可以告诉PDO在构造函数执行之后分配属性。为此,必须使用PDO::FETCH_PROPS_LATE常量。

使用fetchAll()将非常简单.

  1. class User { 
  2.  
  3.     public function __construct($car) { 
  4.  
  5.         $this->car = $car
  6.  
  7.     } 
  8.  
  9.  
  10. $stmt  = $pdo->query('SELECT name, car FROM users LIMIT 1'); 
  11.  
  12. $users = $stmt->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'User', ['Caterpillar']); 

在获取单个行时,我们需要同时调用setFetchMode()和fetchObject(),这可能有点不方便。

  1. class User { 
  2.  
  3.     public function __construct($car) { 
  4.  
  5.         $this->car = $car
  6.  
  7.     } 
  8.  
  9.  
  10. $stmt = $pdo->query('SELECT name, car FROM users LIMIT 1'); 
  11.  
  12. $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'User'); 
  13.  
  14. $user = $stmt->fetchObject('User', ['Caterpillar']); 
  15.  
  16. /* 
  17.  
  18. object(User)#3 (2) { 
  19.  
  20.   ["car"]  => string(6) "Toyota" 
  21.  
  22.   ["name"] => string(4) "John" 
  23.  
  24. } */ 

如上这段代码效率并不高,因为我们必须编写两次类名。

或者,我们可以使用fetch():

  1. $stmt = $pdo->query('SELECT name, car FROM users LIMIT 1'); 
  2.  
  3. $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'User', ['Caterpillar']); 
  4.  
  5. $user = $stmt->fetch(); 

但是,如上所述,如果一个类恰好是未定义的,它将无法帮助我们处理错误消息。

从数据库中获取类名

还有一个更有趣的标志,它告诉PDO从第一列的值中获取类名。使用这个标志,可以避免使用setFetchMode()和fetch():

  1. $data = $pdo->query("SELECT 'User', name FROM users"
  2.  
  3.             ->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); 
  4.  
  5. /* 
  6.  
  7. object(User)#3 (1) { 
  8.  
  9.   ["name"]=> string(4) "John" 
  10.  
  11. } */ 

此外,如果可以从同一个查询创建不同类的对象,那么这种模式将非常有用

  1. class Male {}; 
  2.  
  3. class Female {}; 
  4.  
  5. $stmt = $pdo->query('SELECT sex, name FROM users'); 
  6.  
  7. $users = $stmt->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); 
  8.  
  9. /* 
  10.  
  11. array(6) { 
  12.  
  13.   [0]=> object(Male)#3 (1) { 
  14.  
  15.     ["name"]=> string(4) "John" 
  16.  
  17.   } 
  18.  
  19.   [1]=> object(Male)#4 (1) { 
  20.  
  21.     ["name"]=> string(4) "Mike" 
  22.  
  23.   } 
  24.  
  25.   [2]=> object(Female)#5 (1) { 
  26.  
  27.     ["name"]=> string(4) "Mary" 
  28.  
  29.   } 
  30.  
  31.   [3]=> object(Female)#6 (1) { 
  32.  
  33.     ["name"]=> string(5) "Kathy" 
  34.  
  35.   } 
  36.  
  37. }*/ 

然而,当使用这种模式时,似乎不可能在类构造函数中传递任何参数。

更新现有对象

除了创建新对象,PDO还可以更新现有对象。只使用setFetchMode(),它将现有变量作为参数。显然,使用fetchAll()是无用的。

  1. class User 
  2.  
  3.  
  4.     public $name
  5.  
  6.     public $state
  7.  
  8.  
  9.  
  10.     public function __construct() 
  11.  
  12.     { 
  13.  
  14.         $this->name = NULL; 
  15.  
  16.     } 
  17.  
  18.  
  19. $user = new User; 
  20.  
  21. $user->state = "up'n'running"
  22.  
  23. var_dump($user); 
  24.  
  25.  
  26.  
  27. $stmt = $pdo->query('SELECT name FROM users LIMIT 1'); 
  28.  
  29. $stmt->setFetchMode(PDO::FETCH_INTO, $user); 
  30.  
  31. $data = $stmt->fetch(); 
  32.  
  33. var_dump($data$user); 
  34.  
  35. /* 
  36.  
  37. object(Foo)#2 (2) { 
  38.  
  39.   ["name"]  => NULL 
  40.  
  41.   ["state"] => string(12) "up'n'running" 
  42.  
  43. } 
  44.  
  45. object(Foo)#2 (2) { 
  46.  
  47.   ["name"]  => string(4) "John" 
  48.  
  49.   ["state"] => string(12) "up'n'running" 
  50.  
  51. } 
  52.  
  53. object(Foo)#2 (2) { 
  54.  
  55.   ["name"]  => string(4) "John" 
  56.  
  57.   ["state"] => string(12) "up'n'running" 
  58.  
  59. } */ 

如上,fetch()调用返回的是相同的对象,这在我看来是多余的。还要注意,与PDO::FETCH_CLASS不同,这种模式不分配私有属性。

Tags: 获取PDO对象

分享到: