其他用于DB对象交互的PHP类设计是什么?

其他用于DB对象交互的PHP类设计是什么?,php,class-design,Php,Class Design,我有一个名为“User”的表,它保存用户信息。我将调用我的用户类并创建一个用户对象,以便获取该用户所需的任何信息 我一直在我的网站上使用下面的类和它们的混合体,但从来没有真正对它们感到满意,主要是因为我不确定其他开发人员如何处理这种情况,以及是否有更好的解决方案。下面是我一直在使用的一些方法,我很想看看其他开发人员是怎么做的 想法#1 想法2 Idea#1似乎是最有效的,或者说是最少数量的DB调用,但比Idea#2更复杂、更简单 我更喜欢idea#2,但我担心它的可伸缩性,因为每个函数都会调用D

我有一个名为“User”的表,它保存用户信息。我将调用我的用户类并创建一个用户对象,以便获取该用户所需的任何信息

我一直在我的网站上使用下面的类和它们的混合体,但从来没有真正对它们感到满意,主要是因为我不确定其他开发人员如何处理这种情况,以及是否有更好的解决方案。下面是我一直在使用的一些方法,我很想看看其他开发人员是怎么做的

想法#1

想法2

Idea#1似乎是最有效的,或者说是最少数量的DB调用,但比Idea#2更复杂、更简单

我更喜欢idea#2,但我担心它的可伸缩性,因为每个函数都会调用DB


想法

我建议您使用像Yii这样的PHP框架

它具有很好的特性,可以在类和数据库之间进行交互。
如果你真的想自己做这件事,你也可以从中得到一些启发。

首先,用户对象是用来保存用户数据的,所以我建议方法1,方法2更像是一个amodel对象,它发送用户的命令来获取数据

现在,您可以在一个查询中将用户行自动映射到一个对象,例如:

class User
{
    //Predefine Here
    public $id;
    public $username;
    public $password;
    public $email;
    public $hash;

    public function profileLink()
    {
         return sprintf('<a href="/profile/%s">%s</a>',$this->id,$this->username);
    }
}

//Fetch the results

$result = $sth->fetchAll(PDO::FETCH_CLASS, "User");
$userObjects = array();
foreach($result as $user)
{
    $userObjects[] = $user;
}

//Now you can use like so:

echo $userObjects[2]->profileLink();
类用户
{
//在此预定义
公费$id;
公共$username;
公共密码;
公费邮件;
公共$hash;
公共函数profileLink()
{
返回sprintf(“”,$this->id,$this->username);
}
}
//取得结果
$result=$sth->fetchAll(PDO::FETCH_类,“用户”);
$userObjects=array();
foreach($result as$user)
{
$userObjects[]=$user;
}
//现在您可以这样使用:
echo$userObjects[2]->profileLink();

因此,我的另一个答案是:

类似这样的东西怎么样:

class Db
{
    function __construct()
    {
        $this->engine = DB_ENGINE;
        $this->dbname = DB_NAME;
        $this->host = DB_HOST;
        $this->username = DB_USERNAME;
        $this->password = DB_PASSWORD;

        $this->connect();
    }

    function connect()
    {
        $this->db = new PDO($this->engine.':host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password);
    }
}

class Table extends Db
{
    protected $from = null;

    function __construct()
    {
        parent::__construct();
    }

    function select($columns, $where, $order, $offset, $limit)
    {
    }

    function update($where, $data)
    {
    }

    function delete($where)
    {
    }

    etc...

}

class User extends Table
{
    function __construct()
    {
        parent::__construct();
        $this->from = 'blog';
    }

    function get_user()
    {
        $this->select(params);
    }

    function get_user_count()
    {
    }

    etc...
}

通过这种方式,您可以轻松地使用它获取其他信息,也可以创建一个新类,其中包含检索/删除/等信息的函数。

我认为,如果您要实现自己的用户类,那么它应该类似于以下内容:

class User {
    private $UserID;
    private $Username;
    private $AvatarImg;
    // ... First Name, Last Name, ALL other user information that you store in the DB.

    function __construct( $uid ) {
        // Populate all private members from the DB for the given user id.
    }

    function update( $assocArrayOfValues ) {
        // Commit these values to the Db and Update the private members.
    }

    // All Associated get functions ( getName, getUID, getUsername etc )
    // Any other specialty functions you may want, e.g...
    function getAvatar() {
        return "<img src = '" . $this->AvatarImg . "'/>";
    }

}
类用户{
私有$UserID;
私有$Username;
私有$RIMG;
//…名字、姓氏以及存储在数据库中的所有其他用户信息。
函数构造($uid){
//为给定的用户id填充数据库中的所有私有成员。
}
函数更新($assocarayofvalues){
//将这些值提交到数据库并更新私有成员。
}
//所有相关的get函数(getName、getUID、getUsername等)
//您可能需要的任何其他专业功能,例如。。。
函数getAvatar(){
返回“AvatarImg.”“/>”;
}
}

您试图归档的是ORM(对象关系映射器)的功能。使用ORM(对象关系映射器)而不是自己归档可能会有好处

如果你想自己做,我会选择延迟加载。这有点介于你的两个想法之间。在PHP中,它看起来像这样:

class User
{ 
    private $id; // depends on your application, could also be a string
    private $dirty;
    private $loaded;

    private $properties;

    public function __construct($user_id)
    {
        $this->id = $user_id;
    }

    public function __destruct()
    {
        if ($this->dirty) {
            // commit to DB
        }
    }

    public function __get($name)
    {
        if (!$loaded)
        {
            $this->loadFromDb();
        }
        // error-handling if the key does not exist is missing here!
        return $this->properties[$name];
    }

    public function __set($name, $value)
    {
        // May be required to load the data here...

        // error-handling if the key does not exist is missing here!
        $properties[$name] = $value;
        $this->dirty = true;
    }

    private function loadFromDb()
    {
        // query data from db and store it in properties
    }
}
这种设计的优点是,如果您构造了最终不需要的对象,那么还没有任何内容涉及到数据库

如果有时加载集合,则让函数从DB加载一组行,并在创建对象时将这些行作为参数传递给构造函数可能会很有用。如果您自己构建每个对象,则这只需要一个查询,而不需要数百个查询


作为进一步的增强,您可以提供一个
User::reset()
函数,该函数将丢弃所做的所有更改。

我建议您了解模式。基本思想如下:

让我们假设(为了示例),您有一个处理书籍的应用程序的MVC结构

  • 拥有一个负责管理不同书籍的域逻辑的模型
    是有意义的
  • 该模型处理数量未知的
    书籍
    实例(图书馆中有许多书籍)。
    每本书
    • 了解自己的一切(作者、出版日期、语言等)
    • 不知道它存储在哪里或数据来自哪里
    • 可以与数据库中的表相关,但包含来自多个表的信息
  • 然后您有一个
    BookMapper
    类的实例,它
    • 模型在构造函数中接收(实现预定义接口)
    • 知道如何(以及在何处)存储
      书籍
      对象,以及如何将数据读入其中
    • 如果存储介质发生变化,可以切换到其他对象
    • 如果它与DB一起工作,那么它在构造函数中已经请求了一个DB对象(比如PDO)
    • 有方法
      存储(Book$Book)
      检索(Book$Book)
      用于保存书籍数据或从存储中获取新信息

这就是我要做的。

看看Active Record设计模式:我真的很喜欢拥有一个包含更新、选择和删除方法的表类的想法。这很有意义,因为你可以在任何对象类中包含它们。可能只是我……但用户不是表的形式,也不是DB的形式。这没有意义“形式的”-“类型的”、“种类的”、“子集的”、“品种的”、“品种的”、“子类的”、“类别的”我明白什么“不是一种形式“意思是。我想知道为什么您认为用户不是表的子类。通过编写User extends Table,用户将成为Table的一个子类。您可以调用Table,UserMapper,并使其特定于用户类,但我假设PeeHaa正在尝试创建一个通用映射器类。这样他就不需要创建BookMapper或UserMapper了
class User {
    private $UserID;
    private $Username;
    private $AvatarImg;
    // ... First Name, Last Name, ALL other user information that you store in the DB.

    function __construct( $uid ) {
        // Populate all private members from the DB for the given user id.
    }

    function update( $assocArrayOfValues ) {
        // Commit these values to the Db and Update the private members.
    }

    // All Associated get functions ( getName, getUID, getUsername etc )
    // Any other specialty functions you may want, e.g...
    function getAvatar() {
        return "<img src = '" . $this->AvatarImg . "'/>";
    }

}
class User
{ 
    private $id; // depends on your application, could also be a string
    private $dirty;
    private $loaded;

    private $properties;

    public function __construct($user_id)
    {
        $this->id = $user_id;
    }

    public function __destruct()
    {
        if ($this->dirty) {
            // commit to DB
        }
    }

    public function __get($name)
    {
        if (!$loaded)
        {
            $this->loadFromDb();
        }
        // error-handling if the key does not exist is missing here!
        return $this->properties[$name];
    }

    public function __set($name, $value)
    {
        // May be required to load the data here...

        // error-handling if the key does not exist is missing here!
        $properties[$name] = $value;
        $this->dirty = true;
    }

    private function loadFromDb()
    {
        // query data from db and store it in properties
    }
}