如何使用 pdo 作为 getter 来最好地获取数据

Posted

技术标签:

【中文标题】如何使用 pdo 作为 getter 来最好地获取数据【英文标题】:How to best fetch data with pdo as a getter 【发布时间】:2013-10-17 07:53:42 【问题描述】:

我希望你们能对我的问题有所了解。我需要的基本上是从数据库行(实例获取器)获取和分配属性的最佳实践。这是一个非常标准的问题,我知道它在 C# 中是如何工作的,但我不清楚如何在 php 中完成类似的结果,也没有找到任何满足我需求的在线解决方案。

假设我有这个简化的代码:

Class User
  private $Pdo;
  private $UserID;
  private $UserName;

  function GetUserName()
    return $this->UserName;
    

  function GetUserInfo()
    // return user object with given user id, in this example just use "1"
    $Pdo = $this->Pdo;
    $Query = $Pdo->query('select * from User where UserID = 1');
    $Query->setFetchMode(PDO::FETCH_CLASS, "User", array($Pdo) ); // this is returning object
    $UserInfo = $Query->fetch();
    return $UserInfo;
    

  

然后,当我想获取用户对象时,我会这样称呼它:

$User = new User($Pdo);
$UserInfo = $User->GetUserInfo();
echo $UserInfo->GetUserName();

这行得通,但是我不喜欢这样做。一种选择是使用静态方法,所以最后我会得到类似的结果:

$UserInfo = User::GetUserInfo()

我认为这被称为“单身人士”(编辑:不是单身人士:)),通常被认为是不好的做法。

我的问题是它应该是什么样子?我想要的是这样的:

$UserInfo = new User($Pdo);
$UserInfo->GetUserInfo();
echo $UserInfo->GetUserName();

我知道在 GetUserInfo 方法中我可以手动将值分配给当前对象 ($this),例如:

function GetUserInfo()
    // get data from db
    $this->UserName = "John"; // this value I will get from db
   

但是我想使用 FetchClass,这样我就可以在一行中根据它们的名称获取所有属性,而不是手动分配它们。我希望你明白我的问题是什么:) 我很想听听你对什么是最好的方法的意见。

非常感谢您的任何意见。

【问题讨论】:

User::GetUserInfo() 不是单例,而是静态方法。单例只是只允许实例化一次的对象。 好的,不知道 :) 我看到类似的例子并认为是它。 【参考方案1】:

朝着最佳实践和良好设计方向迈出的一步是将域模型和持久层分开。

因此,您可以独立于所使用的数据库,甚至可以使用 Web 服务替换数据库。看Data Mapper pattern。

因此,您的 User 模型将仅包含属性 + getter/setter 以及以某种方式使用这些属性的方法(业务逻辑)。

class User

    protected $UserID;
    protected $UserName;

    public function getUserId()
    
        return $this->UserID;
    

    public function setUserId($userId)
    
        $this->UserID = userId;
        return $this;
    

    ...


您的映射器持有数据库连接并负责保存/获取User 对象。

class UserMapper

    protected $_pdo;

    public function __construct($pdo)
    
        $this->_pdo = $pdo;
    

    public function getUserById($id)
    
        // TODO: better use prepared statements!
        $query = $this->_pdo->query("select * from User where UserID = ".id);
        $query->setFetchMode(PDO::FETCH_CLASS, "User");
        return $query->fetch();
    

    public function save(User $user)
    
        // insert/update query
    

    ...


你可以像这样使用它:

$userMapper = new UserMapper($pdo);
$user = $userMapper->getUserById(1);

echo $user->getUserName();

$user->setUserName('Steve');
$userMapper->save($user);

还有其他类似的模式,例如表网关模式。但我更喜欢数据映射器,因为数据源的独立性。

查看 Martin Fowler 的整个目录:Catalog of Patterns of Enterprise Application Architecture

另一个有用的帖子:What is the difference between the Data Mapper, Table Data Gateway (Gateway), Data Access Object (DAO) and Repository patterns?

【讨论】:

您好,谢谢您的回答。我想我可以试试这个。我正在考虑创建 UserInfoProvider 来获取对象,并且您向我确认这应该是一种合理的方法。 我有一个问题 - 我阅读了这篇文章,它指出基本上我的 User 类中甚至没有任何 PDO (Sql) 语句。那么,如果我有一个在给定用户存在的情况下返回真/假的方法,我该怎么办。我必须使用 PDO 和 SQL 来检查用户是否存在于数据库中。但是我必须在 UserClass 中使用这种方法,这对我来说似乎“过于复杂”.. 是的,User 类对持久层一无所知。如果用户不存在,getUserById 方法应该已经返回 null。否则,您可以在映射器中创建类似 userExists($userName) 的方法,该方法返回 true 或 false。但是您是对的,通常使用数据映射器或 ORM 方法存在一些缺陷。另一种选择是使用现成的 ORM 系统,例如 doctrine,它已经解决了许多问题。 一定会去看看的。非常感谢您的宝贵时间。很好的答案。 您好,感谢您的出色回答。我想如果我创建 getUserById(), getUserByName(), getUserNameByID(), ... 那么方法太多了。你有什么想法吗?

以上是关于如何使用 pdo 作为 getter 来最好地获取数据的主要内容,如果未能解决你的问题,请参考以下文章

PDO:在哪里声明数据库连接?

PDO

Firestore、vue、vuex、vuexfire:如何让 getter 真正从存储中获取数据?

如何在使用 PHP-PDO 记录查询时获取最后一个插入 ID

使用 mysql PDO 获取字符集

PHP 数据对象 (PDO)