PHP OOP 数据库设计
Posted
技术标签:
【中文标题】PHP OOP 数据库设计【英文标题】:PHP OOP database design 【发布时间】:2012-03-27 09:19:04 【问题描述】:好的,这只是一个简单的问题,我可能会对此有所懈怠,但我只是在寻找一些指导,因为我完全是自学成才的。我做了很多阅读并尝试做很多构建——我想说我正在进入一个很好的 php、mysql 和一般网络知识的中间阶段——绝不是高级或过于自信——还在学习。
我真的在尝试解决 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部分---面向对象,设计模式(单例模式工厂模式)oop六大原则;