首页 > 编程技术 > php

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

发布时间:2016-11-25 17:12

我们都知道如何从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()方法(在子类中重写)。

在我最近做的一个项目中,我发现了一个新的概念,关于在PHP中使用变量的变量。在我的程序中,我需要在一个页面同时更新多个记录,在我经过相当长时间的痛苦思考之后,脑海中偶然地闪现出了变量的变量(variable variable)这一概念,所有的困惑就一扫而光了。

介绍

什么叫作变量的变量?根据PHP手册,变量的变量是指取得一个变量的值并把它作为另一个变量的变量名。这表述显得相当的直接,轻易和那些在一个句子中使用“变量”这个词弄混淆。给一个简单的例子,你定义一个变量 --- x 等于 this --- 然后定义一个变量的变量,意味着你把 x 的值作为新变量的名,在这个例子中,这个新变量的值是 is cake。用PHP来表示如下:

<?php

$x = "this";
$$x = "is cake";

?>

这个符号$$是在PHP中对变量的变量的表示方法。现在我们可以用两种不同的方式来引用这两个变量 $x 和 $$x 了。

<?php

echo "$x ${$x}";

?>

<?php

echo "$x $this";

?>

上面两段程序都将输出 this is cake。注重,在echo语句中$$x被写成${$x},这是让PHP知道你要输出的是变量的变量而不是一个$字符与$x变量。

你是不是仍很迷惑?哦,也许吧,你想要一些更深入更有用的例子?下一节,我将向你展示怎样用变量的变量在一个页面编辑多条记录的。

例子

假设你已有一个MySQL数据库,保存了对一些感爱好的站点的链接,库中有一个表submissions,字段如下:

SubmissionID
PostedBy
Link
Description
Approved

现在你想显示在表中所有的已创建但没有被认可的链接,这个编辑的页面应可以更正一些输入时的错误,并用适当的单选按钮来为每一个记录设置是否答应(Approved),然后一次把更新后的记录都提交到表中。

首先,当你从数据库出提取所有的记录并显示出来时,你必须为每一个记录设置一个唯一的名字,这将让我们在提交时可以循环地辩别出各个记录的值。代码如下:

<?php

//初始化变量的记数器

$index = 0;
$index_count = 0;

echo "<form method=post action=$PHP_SELF>n";
echo "<table>n";
echo "<tr><td><b>Posted By</b></td><td><b>Link</b></td>".
"<td><b>Description</b></td><td><b>Approved</b></td></tr>n";


/*********
假定我们已从数据库中检索出记录到一个数组中 
$myrow = mysql_fetch_array().
下面的 do...while 循环根据名字为每一个$xstr变量分配了一个值并且连接了$index 的值到结尾,以0为开始。
这样,这个循环的第一次时,$SubmissionIDStr 的值就是 SubmissionID0 ,第二次就是 SubmissionID1 ,以此类推。
***********/

do {

$SubmissionIDStr = SubmissionID.$index;
$PostedByStr = PostedBy.$index;
$LinkStr = Link.$index;
$DescriptionStr = Description.$index;
$ApprovedStr = Aprroved.$index;


//这一段将在屏幕上显示值,以每行一条记录。

在 PHP5 中多了一系列新接口。在 HaoHappy 翻译的系列文章中 你可以了解到他们的应用。同时这些接口和一些实现的 Class 被归为 Standard PHP Library(SPL)。在 PHP5 中加入了很多特性,使类的重载 (Overloading) 得到进一步的加强。ArrayAccess 的作用是使你的 Class 看起来像一个数组 (PHP的数组)。这点和 C# 的 Index 特性很相似。

下面是 ArrayAccess 的定义:

interface ArrayAccess
boolean offsetExists($index)
mixed offsetGet($index)
void offsetSet($index, $newvalue)
void offsetUnset($index)

由于PHP的数组的强大,很多人在写 PHP 应用的时候经常将配置信息保存在一个数组里。于是可能在代码中到处都是 global。我们换种方式?

如以下代码:

//Configuration Class
class Configuration implements ArrayAccess
{

static private $config;

private $configarray;

private function __construct()
{
// init
$this->configarray = array("Binzy"=>"Male", "Jasmin"=>"Female");
}

public static function instance()
{
//
if (self::$config == null)
{
self::$config = new Configuration();
}

return self::$config;
}

function offsetExists($index)
{
return isset($this->configarray[$index]);
}

function offsetGet($index) {
return $this->configarray[$index];
}

function offsetSet($index, $newvalue) {
$this->configarray[$index] = $newvalue;
}

function offsetUnset($index) {
unset($this->configarray[$index]);
}
}

$config = Configuration::instance();
print $config["Binzy"];


正如你所预料的,程序的输出是"Male"。
假如我们做下面那样的动作:

$config = Configuration::instance();
print $config["Binzy"];
$config['Jasmin'] = "Binzy's Lover";
// config 2
$config2 = Configuration::instance();
print $config2['Jasmin'];

是的,也正如预料的,输出的将是Binzy's Lover。
也许你会问,这个和使用数组有什么区别呢?目的是没有区别的,但最大的区别在于封装。OO 的最基本的工作就是封装,而封装能有效将变化置于内部。也就是说,当配置信息不再保存在一个 PHP 数组中的时候,是的,应用代码无需任何改变。可能要做的,仅仅是为配置方案添加一个新的策略(Strategy)。:

ArrayAccess 在进一步完善中,因为现在是没有办法 count 的,虽然大多数情况并不影响我们的使用。

参考:
1. 《PHP5 Power Programming》
2. 《设计模式》
3. 《面向对象分析与设计》

MySQL的“SET NAMES xxx”字符集问题分析

还有一篇关于Apache和PHP编码的:http://www.111cn.net/bbs/thread-13860-1-1.html

近来接受BBT的培训,做一个投票系统。系统代码倒不是很难,但是我的时间主要花费在了研究字符集和

编码上面。MySQL和Apache两个系统的编码(字符集)问题让我费劲脑筋,吃尽苦头。网上对这些问题的

解决比较零散,比较片面,大部分是提供解决方法,却不说为什么。于是我将这几天收获总结一下,避免

后来者再走弯路。这篇文章对PHP编写有一点帮助(看完你就知道,怎样让你的PHP程序在大部分空间提供

商的服务器里显示正常),但是更多帮助在于网络服务器的架设和设置。
先说MySQL的字符集问题。Windows下可通过修改my.ini内的
复制内容到剪贴板代码:
# CLIENT SECTION

[mysql]

default-character-set=utf8

# SERVER SECTION

[mysqld]

default-character-set=utf8
这两个字段来更改数据库的默认字符集。第一个是客户端默认的字符集,第二个是服务器端默认的字符集

。假设我们把两个都设为utf8,然后在MySQL Command Line Client里面输入“show variebles like

“character_set_%”;”,可看到如下字符:
character_set_client   latin1
character_set_connection    latin1
character_set_database     utf8
character_set_results    latin1
character_set_server   utf8
character_set_system     utf8
其中的utf8随着我们上面的设置而改动。此时,要是我们通过采用UTF-8的PHP程序从数据库里读取数据,

很有可能是一串“?????”或者是其他乱码。网上查了半天,解决办法倒是简单,在连接数据库之后,读

取数据之前,先执行一项查询“SET NAMES UTF8”,即在PHP里为
复制内容到剪贴板代码:
mysql_query("SET NAMES UTF8");
即可显示正常(只要数据库里信息的字符正常)。为什么会这样?这句查询“SET NAMES UTF8”到底是什

么作用?
到MySQL命令行输入“SET NAMES UTF8;”,然后执行“show variebles like“character_set_%”;”,

发现原来为latin1的那些变量“character_set_client”、“character_set_connection”、

“character_set_results”的值全部变为utf8了,原来是这3个变量在捣蛋。查阅手册,上面那句等于:
复制内容到剪贴板代码:
SET character_set_client = utf8;

SET character_set_results = utf8;

SET character_set_connection = utf8;
看看这3个变量的作用:
信息输入路径:client→connection→server;
信息输出路径:server→connection→results。
换句话说,每个路径要经过3次改变字符集编码。以出现乱码的输出为例,server里utf8的数据,传入

connection转为latin1,传入results转为latin1,utf-8页面又把results转过来。如果两种字符集不兼

容,比如latin1和utf8,转化过程就为不可逆的,破坏性的。所以就转不回来了。
但这里要声明一点,“SET NAMES UTF8”作用只是临时的,MySQL重启后就恢复默认了。
接下来就说到MySQL在服务器上的配置问题了。岂不是我们每次对数据库读写都得加上“SET NAMESUTF8”

,以保证数据传输的编码一致?能不能通过配置MySQL来达到那三个变量默认就为我们要想的字符集?手

册上没说,我在网上也没找到答案。所以,从服务器配置的角度而言,是没办法省略掉那行代码的。
总结:为了让你的网页能在更多的服务器上正常地显示,还是加上“SET NAMES UTF8”吧,即使你现在没

有加上这句也能正常访问。



//函数list
            while(list($id,$username,$password,$add_date,$mdn,$mobile,$channel,$last_date,$area,$nickname) = mysql_fetch_array($rs)){
                    $article[$i]['id'] = $id;
                    $article[$i]['add_date'] = $add_date;
                        $article[$i]['mdn'] = $mdn;
                    $article[$i]['last_date'] = $last_date;
                        $article[$i]['area_id'] = $area;
                        $article[$i]['nickname'] = $nickname;
                    $i ++;
               }

//函数array_push
            while($row  = mysql_fetch_array($rs)){
                    $article = array_push($row);
               }

这两个函数有什么是:
list不创建数组,直接赋值,而push用于追加数组项
 
标签:[!--infotagslink--]

您可能感兴趣的文章: