PHP OOP 数据库设计

Posted

技术标签:

【中文标题】PHP OOP 数据库设计【英文标题】:PHP OOP database design 【发布时间】:2012-03-27 09:19:04 【问题描述】:

好的,这只是一个简单的问题,我可能会对此有所懈怠,但我只是在寻找一些指导,因为我完全是自学成才的。我做了很多阅读并尝试做很多构建——我想说我正在进入一个很好的 phpmysql 和一般网络知识的中间阶段——绝不是高级或过于自信——还在学习。

我真的在尝试解决 PHP 中的 OOP,所以我想为 MySQL 创建一个好的精益数据库包装器,只是 MySQL,我对 MySQL 最满意,我看不出有任何理由使用任何其他数据库。我不想在设计中创建任何形式的可移植性——我希望它特定于我的数据库;所以我不想使用 PDO。

所以我现在开始的问题是我是否应该创建一个扩展 mysqli 的类,然后为我的数据库表创建模型类来扩展该基本数据库类?所以 class->child = mysqli->DbBase->UsersModel ?这将需要类中的大量 $this 语句,不是吗?

或者我应该实例化一个 mysqli 类并将其传递给 DbBase?

【问题讨论】:

我强烈建议你不要使用mysqli。与 PDO 相比,它的界面有很多丑陋的缺陷,而 PDO 远非 PHP 上的标准现代 db API。 【参考方案1】:

类有点代表现实世界中的事物(甚至是虚构的“事物”),对吧?一个 DB 实例代表一个与该 db 的连接。模型与数据库连接有什么共同点吗?并不真地。我建议在您要编写的模型类中包含数据库类的实例,因为模型使用数据库连接来访问它的数据,但 不是一种数据库连接。

关于 Mysqli DBClass:这真的取决于你试图用那个 DBClass 实现什么——它是否通过一些额外的功能或任何东西扩展了 Mysqli?如果没有,不要在那里使用继承,否则你可以使用它。


一个非常基本的例子,只是为了给你一个想法:(它实际上是ActiveRecord模式的简化但绝对不完整的版本)

abstract class DbTable 
    /* An instance of your DBClass (=Database Connection), to be used if no
     * other connection is specified. */
    protected static $_defaultDbAdapter = null;

    /* The db connection to be used by this instance. */
    protected $_dbAdapter = null;

    /* The name of the table in the database. */
    protected $_tableName = '';

    public static function setDefaultDbAdapter(DbClass $db) 
        self::$_defaultDbAdapter = $db;
    

    public function setDbAdapter(DbClass $db) 
        $this->_dbAdapter = $db;
    

    public function getDbAdapter() 
        if (null === $this->_dbAdapter) 
            $this->setDbAdapter(self::$_defaultDbAdapter);
        
        return $this->_dbAdapter;
    

    public function insert(array $data)  /*...*/ 
    public function update(array $data, $where)  /*...*/ 
    public function delete($where)  /*...*/ 
    public function select($where)  /* may e.g. return an array of DbTableRow childclass instances */  

    // ...


class Users extend DbTable 
    protected $_tableName = 'my_users_table';


abstract class DbTableRow 
    /* The row itself (may be not yet saved to the db!) */
    protected $_data = array();

    /* The row as it is in the database (to find differences, when calling save()). */
    protected $_cleanData = array();

    /* An instance of the table that this row belongs to. */
    protected $_table = null;

    public function __construct(DbTable $table, array $data = array())  /*...*/ 
    public function save()  /* uses $this->_table->insert()/update() */ 
    public function __get($key)  /*...*/ 
    public function __set($key, $value)  /*...*/ 
    // ...


class User extends DbTableRow  

用法:

// Make a new connection to the database
$db = new DbClass('...'); // or whatever you name that class...

// Set this connection to be the default connection
DbTable::setDefaultDbAdapter($db);

// Create a new user
$users = new Users();
$user = new User($users);
$user->email = 'test@example.com';
$user->save();

【讨论】:

感谢您的回答,我认为这是迄今为止我一直在寻找的“大部分”,但我没有遵循您的模型方法。在从数据访问对象扩展的类中对表进行建模是否有意义,您可以轻松地拥有诸如 ->save() 之类的方法? 这确实是有道理的。但是表类代表一个表,这也与数据库连接不同,因为它使用一个来访问其数据,但实际上并不是它的一种类型。我强烈建议您查看 Zend_Framework 组件 Zend_Db 和 Zend_Db_Table。我将在我的答案中添加一个示例,我将如何处理这个问题!【参考方案2】:

如果您要使用 OOP,我强烈建议您使用 PDO,因为它是 MySQL 库的最新和 OO 实现。我不认为 PDO-MySQL 比 MySQLi 更不特定于 MySQL。

无论如何,你不应该在这种情况下扩展 PHP 的类,你应该保留一个与数据库连接的对象作为你的类的属性。

您还应该研究 Singleton 设计模式,它在这些情况下非常有用。从今天开始看这个帖子:Move out mysql connection into another class

【讨论】:

好的,谢谢,这听起来不错,但是正确的方法是什么--> 在我的 DbBase 或模型类之外实例化数据库对象,然后将其传递给诸如 __construct 之类的函数然后将其保存为属性或在 __construct 中将其实例化为属性。有什么区别吗? 这取决于您如何设计应用程序,但我认为最好在构造函数中实例化数据库对象。特别是如果你想拥有一个单身人士。然后,您可以在任何地方获取数据库连接的实例,而无需处理数据库登录信息等。 好的,非常感谢,我还在专业 PHP 设计模式一书中找到了一个很好的部分。我在网上有野生动物园书籍,所以如果其他人有它就在这里:link【参考方案3】:

如果你真的想学习和理解 OOP,那么我认为你应该开始学习一些 PHP 框架(如 Zend 框架)并阅读它的源代码。我从他们身上学到了很多东西。

【讨论】:

是的,这对我有帮助,我目前正在查看所有 Yii 基类并尝试学习 Yii。

以上是关于PHP OOP 数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

php面向对象程序设计

php部分---面向对象,设计模式(单例模式工厂模式)oop六大原则;

PHP 中的 OOP 方法

PHP 面向对象程序设计(oop)学习笔记 - 抽象类对象接口instanceof 和契约式编程

什么是OOP

Java oop