首页 » PHP和MySQL Web开发(原书第4版) » PHP和MySQL Web开发(原书第4版)全文在线阅读

《PHP和MySQL Web开发(原书第4版)》6.9 编写类代码

关灯直达底部

在确定了代码的最终运行结果的式样,以及所需的一些特性后,应该开始考虑如何实现它们。在本章的后续内容中,我们将介绍大型项目的设计和管理。现在,我们先集中介绍编写面向对象的PHP脚本部分。

类需要一个逻辑名称。因为它代表一个页面,所以称之为Page。要声明这个Page类,可以使用如下所示的代码:

class Page

{

}

Page类需要一些属性,需要将那些可能要在页与页之间不断修改的元素设置为类的属性。

页面的主要内容,也就是HTML标签和文本的组合,我们将其命名为$content。可以在类定义中使用如下所示的代码来声明它:

public$content;

也可以设置属性来保存页面的标题。我们可能会对其进行修改,从而确保能够清楚地显示访问者浏览的特定页面。为了不让页面标题为空,可以使用如下所示的声明来提供一个默认标题:

public$title=/"TLA Consulting Pty Ltd/";

大多数商业网站的网页都包含了metatags,这样便于搜索引擎对其检索。为了使其更实用,不同页面的metatags应该尽可能不同。同样,我们可以提供一个默认值,如下所示:

public$keywords=/"TLA Consulting,Three Letter Abbreviation,

some of my best friends are search engines/";

图5-2(请参阅第5章)显示的原始页面上的导航条应该在每一页面都应该相同,这样可以避免浏览者混淆。但为了使它们修改起来更加容易,我们也赋给它们一个属性。由于按钮的数量在不同页面可能会有所不同,因此需要使用一个数组,来保存按钮的文本标签以及该按钮指向的URL:

public$buttons=array(/"Home/"=>/"home.php/",

/"Contact/"=>/"contact.php/",

/"Services/"=>/"services.php/",

/"Site Map/"=>/"map.php/"

);

要提供这些功能,类也需要一些操作。可以从定义访问函数来设置和获得已定义的变量值开始。这些函数定义如下所示:

public function__set($name,$value)

{

$this->$name=$value;

}

__set函数不包含错误检查(从简化的角度出发),但是该功能可随后轻松增加。因为你从类的外部请求这些值是不可能的,所以在此可选择不提供__get函数。

该类的主要功能是显示HTML页面,因此我们需要一个显示函数。该函数名称为Display,其代码如下所示:

public function Display

{

echo/"<html>n<head>n/";

$this->DisplayTitle;

$this->DisplayKeywords;

$this->DisplayStyles;

echo/"</head>n<body>n/";

$this->DisplayHeader;

$this->DisplayMenu($this->buttons);

echo$this->content;

$this->DisplayFooter;

echo/"</body>n</html>n/";}

该函数包含了几个简单的、用来显示HTML代码的回显语句,但主要包含对类中其他函数的调用。从它们的名字可以猜出,这些被调用的函数显示页面各个部分。

像这样将各个函数分成多块不是必需的。所有这些分离的函数可以简单地合成一个大函数。我们将它们分开是有一些原因的。

每个分离的函数可以执行一个明确的任务。任务越简单,编写与测试这个函数就越简单。当然也不要将这个函数分得太小——若将程序分成太多的小个体,读起来就会很困难。

使用继承可以重载操作。我们可以替换成一个大的Display函数,但是改变整个页面的显示方式几乎是不可能的。将显示功能分成几个独立的任务则更好,这样我们可以只需重载需要改变的部分。

Display函数调用了DisplayTitle、DisplayKeywords、DisplayStyles、DisplayHeader、DisplayMenu和DisplayFooter。这就意味着需要定义这些操作。我们可以按照这个逻辑顺序编写这些函数或操作,而且可以在具体代码之前调用它们。在许多其他语言中,只有在编写了函数或操作之后才能调用它们。大多数操作都相当简单,只需显示一些HTML,也可能要显示一些属性的内容。

程序清单6-1完整地显示了该类,我们将它保存为page.inc,它可以包含或被包含于其他文件。

程序清单6-1 page.inc——page类提供了简单灵活的方法来创建TLA页面

<?php

class Page

{

//class Page/'s attributes

public$content;

public$title=/"TLA Consulting Pty Ltd/";

public$keywords=/"TLA Consulting,Three Letter Abbreviation,

some of my best friends are search engines/";

public$buttons=array(/"Home/"=>/"home.php/",

/"Contact/"=>/"contact.php/",

/"Services/"=>/"services.php/",

/"Site Map/"=>/"map.php/"

);

//class Page/'s operations

public function__set($name,$value)

{

$this->$name=$value;

}

public function Display

{

echo/"<html>n<head>n/";

$this->DisplayTitle;

$this->DisplayKeywords;

$this->DisplayStyles;

echo/"</head>n<body>n/";

$this->DisplayHeader;

$this->DisplayMenu($this->buttons);

echo$this->content;

$this->DisplayFooter;

echo/"</body>n</html>n/";

}

public function DisplayTitle

{

echo/"<title>/".$this->title./"</title>/";

}

public function DisplayKeywords

{

echo/"<meta name=/"keywords/"

content=/"/".$this->keywords./"/"/>/";

}

public function DisplayStyles

{

?>

<style>

h1{

color:white;font-size:24pt;text-align:center;

font-family:arial,sans-serif

}

.menu{

color:white;font-size:12pt;text-align:center;

font-family:arial,sans-serif;font-weight:bold

}

td{

background:black

}

p{

color:black;font-size:12pt;text-align:justify;

font-family:arial,sans-serif

}

p.foot{

color:white;font-size:9pt;text-align:center;

font-family:arial,sans-serif;font-weight:bold

}

a:link,a:visited,a:active{

color:white

}

</style>

<?php

}

public function DisplayHeader

{

?>

<table cellpadding=/"12/"

cellspacing=/"0/"border=/"0/">

<tr bgcolor=/"black/">

<td ><img src=/"logo.gif/"/></td>

<td>

<h1>TLA Consulting Pty Ltd</h1>

</td>

<td ><img src=/"logo.gif/"/></td>

</tr>

</table>

<?php

}

public function DisplayMenu($buttons)

{

echo/"<table width=/"100%/"bgcolor=/"white/"

cellpadding=/"4/"cellspacing=/"4/">n/";

echo/"<tr>n/";

//calculate button size

$width=100/count($buttons);

while(list($name,$url)=each($buttons)){

$this->DisplayButton($width,$name,$url,

!$this->IsURLCurrentPage($url));

}

echo/"</tr>n/";

echo/"</table>n/";

}

public function IsURLCurrentPage($url)

{

if(strpos($_SERVER[/'PHP_SELF/'],$url)==false)

{

return false;

}

else

{

return true;

}

}

public function

DisplayButton($width,$name,$url,$active=true)

{

if($active){

echo/"<td width=/"/".$width./"%/">

<a href=/"/".$url./"/">

<img src=/"s-logo.gif/"alt=/"/".$name./"/"border=/"0/"/></a>

<a href=/"/".$url./"/"><span class=/"menu/">/".$name./"</span></a>

</td>/";

}else{

echo/"<td width=/"/".$width./"%/">

<img src=/"side-logo.gif/">

<span class=/"menu/">/".$name./"</span>

</td>/";

}

}

public function DisplayFooter

{

?>

<table bgcolor=/"black/"cellpadding=/"12/"border=/"0/">

<tr>

<td>

<p>©TLA Consulting Pty Ltd.</p>

<p>Please see our<a href=/"/">legal

information page</a></p>

</td>

</tr>

</table>

<?php

}

}

?>

当阅读这个类的时候,请注意函数DisplayStyles、DisplayHeader和DisplayFooter需要显示没有经过PHP处理的大量静态HTML。因此,我们简单地使用了PHP结束标记(?>)、输入HTML,然后再在函数体内部使用一个PHP打开标记(<?php)。

该类还定义了其他两个操作。操作DisplayButton将输出一个简单的菜单按钮。如果该按钮指向当前所在的页面,将显示一个没有激活的按钮,这时它看起来就有点不同,并且不指向任何页面。这就使得整个页面布局和谐,并且访问者可看出自己的位置。

操作IsURLCurrentPage将判断按钮URL是否指向当前页。如今有许多技术可以实现它。

这里,我们使用了字符串函数strpos,它可以查看给定的URL是否包含在服务器设置的变量中。strpos($__SERVER[/'PHP_SELF/'],$url)语句将返回一个数字(如果$url中的字符串包含在全局变量$_SERVER[/'PHP_SELF/'])或者false(如果没有包含在全局变量中)。

要使用Page类,需要在脚本语言中包含page.inc来调用Display函数。

程序清单6-2中的代码将创建TLA咨询公司的首页,并且产生与第5章的图5-2非常类似的输出。

程序清单6-2中的代码将实现如下功能:

1)使用require语句包含page.inc的内容,page.inc中包含了Page类的定义。

2)创建了Page类的一个实例。该实例称为$homepage。

3)设定内容,包括页面显示的文本和HTML标记(这将间接地调用__set方法)。

4)在对象$homepage中调用操作Display,使页面显示在访问者的浏览器中。

程序清单6-2 home.php——首页使用Page类完成生成页面内容的大部分工作

<?php

require(/"page.inc/");

$homepage=new Page;

$homepage->content=/"<p>Welcome to the home of TLA Consulting.

Please take some time to get to know us.</p>

<p>We specialize in serving your business needs

and hope to hear from you soon.</p>/";

$homepage->Display;

?>

在以上的程序清单中可以看出,如果使用Page类,我们在创建新页面的时候只要做少量工作。通过这种方法使用类意味着所有页面都必须很相似。

如果希望网站的一些地方使用不同的标准页,只要将page.inc复制到名为page2.inc的新文件里,并做一些改变就可以了。这意味着每一次更新或修改page.inc时,要记得对page2.inc进行同样的修改。

一个更好的方法是用继承来创建新类,新类从Page类里继承大多数功能,但是必须重载需要修改的部分。对于TLA网站来说,要求服务页包含另一个导航条。程序清单6-3所示的脚本通过创建一个继承了Page的名为ServicesPage的新类来实现它。我们提供了一个名为$row2buttons的新数组,它包含出现在第二行中的按钮和链接。因为我们希望该类和其他类的大部分风格相同,因此只需要重载许要修改的部分——Display操作。

程序清单6-3 services.php——services页面继承了Page类,但是重载了Display操作,从而改变了其输出结果

<?php

require(/"page.inc/");

class ServicesPage extends Page

{

private$row2buttons=array(

/"Re-engineering/"=>/"reengineering.php/",

/"Standards Compliance/"=>/"standards.php/",

/"Buzzword Compliance/"=>/"buzzword.php/",

/"Mission Statements/"=>/"mission.php/"

);

public function Display

{

echo/"<html>n<head>n/";

$this->DisplayTitle;

$this->DisplayKeywords;

$this->DisplayStyles;

echo/"</head>n<body>n/";

$this->DisplayHeader;

$this->DisplayMenu($this->buttons);

$this->DisplayMenu($this->row2buttons);

echo$this->content;

$this->DisplayFooter;

echo/"</body>n</html>n/";

}

}

$services=new ServicesPage;

$services->content=/"<p>At TLA Consulting,we offer a number

of services.Perhaps the productivity of your employees would

improve if we re-engineered your business.Maybe all your business

needs is a fresh mission statement,or a new batch of

buzzwords.</p>/";

$services->Display;

?>

重载后的函数Display与原函数是非常相似的,但它包含了额外的一行:

$this->DisplayMenu($this->row2buttons);

它可以第二次调用DisplayMenu,再创建一个菜单条。

在类的定义之外,我们创建了类ServicesPage的一个实例。设置我们不希望的默认值,并调用Display。

如图6-2所示,我们创建了新的不同标准页。需要编写的新代码只是那些不同部分的代码。

图 6-2 通过继承创建services页,重用标准页的大部分代码

通过PHP类创建页面的好处是显而易见的,通过用类完成了大部分工作,在创建页面的时候,我们就可以做更少的工作。在更新页面的时候,只要简单地更新类即可。通过继承,我们还可从最初的类派生出不版本的类而不会破坏这些优势。

当然,就像现实生活中的事情一样,有所得必有所失,这些优点出现也伴随着一定的代价。用脚本创建网页要求更多计算机处理器的处理操作,因为它并不是简单地从硬盘载入静态HTML页然后再送到浏览器。在一个业务繁忙的网站中,处理速度是很重要的,应该尽量使用静态HTML网页,或者尽可能缓存脚本输出,从而减少在服务器上的载入操作。