快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

在数据库中使用对象的好处

我们都知道如何从Mysql获取我们需要的行(记录),读取数据,然后存取一些改动。很明显也很直接,在这个过程背后也没有什么拐弯抹角的。然而对于我们使用面对对象的程序设计(OOP)来治理我们数据库中的数据时,这个过程就需要大大改进一下了。这篇文章将对如何设计一个面对对象的方法来治理数据库的记录做一个简朴的描述。你的数据当中的所有内部逻辑关系将被封装到一个异常条理的记录对象,这个对象能够提供专门(专一)的确认代码系统,转化以及数据处理。随着Zend Engine2 和PHP5的发布,PHP开发者将会拥有更强盛的面对对象的工具来辅助工作,这将使这个过程(面对对象地治理数据库)更有吸引力。

以下列出了一些使用对象来描叙你的数据库的有利方面:


存取方式(Accessor methods)将会使你对属性的读取和写入过程做到完全的控制
每一级的每个记录和属性(的操作)都有确认过程
从关系表中智能的获取对象
重复使用的逻辑方式意味着所有的数据交互都要通过一样的基础代码(codebase),这将使维护变得更加简朴
代码简朴,因为不同的记录的内部逻辑都已经包含在各自所处的类(class)当中,而不是繁琐的库(lib)文件
在手工编写代码和SQL查询语句时,出错的机会将更少


存取方式(Accessor methods)

存取方法是通过类给实例(instance)的变量赋值。一个例子,我有一个叫User的类,并且有一个实例$username,我会写这样的存取方式(函数),User->username()和User->setUsername()用来返回和给实例赋值。



<?php
class User {
var $username;

function username() {
return $this->username;
}

function setUsername($newUsername) {
$this->username = $newUsername;
}
}
?>




这里有很好的理由让我们编写这样的“特殊的代码”。它将使开发者更灵活的改变类的繁琐的工作,因为这一过程将不需要其他的使用类的php代码。让我们来看看下面这个更加完善的可信赖的User类。


变量$username将不复存在,所有的东西都被整合的放在数组$_data当中
假如username是空的话,username()函数将提供一个缺省(默认)的值给它
setUsername()过程将在接受值之前确认username是否合乎标准格式(如字长等)

<?php
class User {
var $_data = array(); // associative array containing all the attributes for the User

function username() {
return !empty($this->_data[\\\'username\\\']) ? $this->_data[\\\'username\\\'] : \\\'(no name!)\\\';
}

function setUsername($newUsername) {
if ($this->validateUsername($newUsername)) {
$this->_data[\\\'username\\\'] = $newUsername;
}
}

function validateUsername(&$someName) {
if (strlen($someName) > 12) {
throw new Exception(\\\'Your username is too long\\\'); // PHP5 only
}
return true;
}
}
?>



显而易见,这对我们控制存取对象的数据有很大帮助。假如一个程序员已经直接地存取username的信息,以上代码的变化将会破坏他的代码。然而我们可以使用(类的)存取方式,就像上面代码中注释的那样,添加一个验证的功能而不需要改变任何其他的东西。注重username的验证(例子当中是不能超过12字节)代码是独立在setUsername()方式之外的。从验证到存储到数据库的过程轻而易举。而且,这是个异常好的单凭经验的方式,一个方式或一个类需要做的越少,它的重复使用的机会将会越大。这在你开始写一个子类时更加明显,如果你需要一个子类,并且又要跳过(忽略)父类方式(行为)中的一些特别的细节,假如(针对这个细节的)方式很小而又精细,(修改它)只是一瞬间的过程,而假如这个方式异常臃肿,针对多种目的,你可能将在复制子类中大量代码中郁闷而终。

比方说,如果Admin是User类的一个子类。我们对adamin的用户可能会有不同的,相对苛刻一些的密码验证方式。最好是跨过父类的验证方式和整个setUsername()方式(在子类中重写)。

更多关于存取器(Accessor)
下面是一些其他的例子来说明如何使存取器用的更有效果。很多时候我们可能要计算结果,而不是简朴的返回数组中的静态数据。存取方式还能做的一个有用的事情就是更新(updating)缓存中的值。当所有的变动(对数据的所有操作)都要通过setX()方式的时候,这正是我们根据X来重置缓存中的值的时刻。

于是我们的这个类层次变得更加明了:

内部变量$_data的处理被替换成受保护的私有方式(private methods)_getData()和_setData()
这类方式被转移到被称作记录(Record)的抽象的超级类(super class),当然它是User类下的子类
这个记录类(Record class)把握所有存取数组$_data的细节,在内容被修改之前调用验证的方式,以及将变更的通知发给记录(Records),就像发给中央对象存储(ObjectStore)实例。

<?php
class User extends Record {

// --- OMITTED CODE --- //

/**
* Do not show the actual password for the user, only some asterixes with the same strlen as the password value.
*/
function password() {
$passLength = strlen($this->_getData(\\\'password\\\'));
return str_repeat(\\\'*\\\', $passLength);
}
/**
* Setting the user password is not affected.
*/
function setPassword($newPassword) {
$this->_setData(\\\'password\\\', $newPassword);
}

/**
* fullName is a derived attribute from firstName and lastName
* and does not need to be stored as a variable.
* It is therefore read-only, and has no \\\'setFullname()\\\' accessor method.
*/
function fullName() {
return $this->firstName() . " " . $this->lastName();
}

/**
* Spending limit returns the currency value of the user\\\'s spending limit.
* This value is stored as an INT in the database, eliminating the need
* for more expensive DECIMAL or DOUBLE column types.
*/
function spendingLimit() {
return $this->_getData(\\\'spendingLimit\\\') / 100;
}

/**
* The set accessor multiplies the currency value by 100, so it can be stored in the database again
* as an INT value.
*/
function setSpendingLimit($newSpendLimit) {
$this->_setData(\\\'spendingLimit\\\', $newSpendLimit * 100);
}

/**
* The validateSpendingLimit is not called in this class, but is called automatically by the _setData() method
* in the Record superclass, which in turn is called by the setSpendingLimit() method.
*/
function validateSpendingLimit(&$someLimit) {
if (is_numeric($someLimit) AND $someLimit >= 0) {
return true;
} else {
throw new Exception("Spending limit must be a non-negative integer"); //PHP5 only
}
}
}

/**
* Record is the superclass for all database objects.
*/
abstract class Record {
var $_data = array();
var $_modifiedKeys = array(); // keeps track of which fields have changed since record was created/fetched

/**
* Returns an element from the $_data associative array.
*/
function _getData($attributeName) {
return $this->_data[$attributeName];
}

/**
* If the supplied value passes validation, this
* sets the value in the $_data associative array.
*/
function _setData($attributeName, $value) {
if ($this->validateAttribute($attributeName, $value)) {
if ($value != $this->_data[$attributeName]) {
$this->_data[$attributeName] = $value;
$this->_modifiedKeys[] = $attributeName;
$this->didChange();
} else {
// the new value is identical to the current one
// no change necessary
}
}
}

/**
* For an attribute named "foo", this looks for a method named "validateFoo()"
* and calls it if it exists. Otherwise this returns true (meaning validation passed).
*/
function validateAttribute($attributeName, &$value) {
$methodName = \\\'validate\\\' . $attributeName;
if (method_exists($this, $methodName)) {
return $this->$methodName($value);
} else {
return true;
}
}

function didChange() {
// notify the objectStore that this record changed
}
}
?>



现在我们拥有了一个抽象的超级类(Record),我们可以将User类里面大量的代码转移出来,而让这个User的子类来关注User的特别项目如存取和验证方式。你可能已经注重到在我们的这个纪录类(Record class)没有任何的SQL代码。这并不是疏忽或者遗漏!对象存储类(ObjectStore class)(隐藏在第二部分)将负责所有和数据库的交互,还有我们的超级类Record的实例化。这样使我们的Record类更加瘦小而又有效率,而这对于评价我们处理大量对象的效率的时候是个重要因素。
返回类别: 教程
上一教程: 关于如何在查询结果中添加自动编号
下一教程: SQL SERVER数据库备份还原另一方式

您可以阅读与"在数据库中使用对象的好处"相关的教程:
· 使用MD5加密数据库中的用户密码
· 使用MD5加密数据库中的用户密码(一)
· 使用MD5加密数据库中的用户密码(二)
· ORACLE数据库游标使用大全
· ASP使用MYSQL数据库全攻略
    微笑服务 优质保证 索取样品