天天看点

PHP5:面向对象 + XML + XSL 实现项目开发的模板化、模块化

PHP5对类的支持已经很强大了,用面向对象的方式 + XML + XSL实现模板化、模块化的项目开发有一个最大的好处:表现层和逻辑层完全分离;并可以根据实际情况选择服务器解析或者客户端解析两种方式来实现 XML + XSL 生成 HTML 。

注意:这里我不涉及运行效率问题(优化运行效率方法很多,这里不讨论)。

在做一个WEB应用的项目的一开始时,我们在作了一定的需求分析后,将整个项目按功能模块来划分好;在将各模块的共同之处抽象出来作为各模块的“父抽象类”;

例如,各模块在逻辑层都需要有“用户”,而在表现层,可能都有页头、页尾,甚至同样的菜单项;

好,我们开始设计这样一个抽象的顶级父类:

CODE:

class abstractModule

{

  protected static $user = null;

  abstract protected function createMenu();

}

这就是一个抽象的各模块的父类!那么我们在运行各模块时,需要判断用户是否登陆时,就可以直接

if(self::$user){

  //已登陆用户

}else{

  //未登陆用户

}

假设我们运行模块需要模块扩展IRunAble这个接口:

CODE:

interface IRunAble{

  public function run();

}

并且我们需要模块支持加载XML和XSL,并能根据参数来判断是直接输出XML还是输出XML+XSL得到的HTML,至于XML和XSL如何被加载的,我们先不考虑,则把上面的abstractModule写的稍微完整一点就是:

CODE:

class abstractModule implements IRunAble

{

  protected static $outPutType = "xml&xsl";

  protected static $user = null;

  abstract protected function createMenu();

  public function run()

  {

    switch($this->$outPutType)

    {

        case "xml":

          echo loadXML();

          break;

        case "xml&xsl":

          $xsl = $this->loadXSL();

          $xml = $this->loadXML();

          if($xsl && $xml) {

            $xslProc = new XSLTProcessor();

            $xslProc->importStyleSheet($xsl);

            echo $xslProc->transFormToXML($xml);  

          }

          break;

    }

  }

  abstract public functon loadXML();

  abstract public function loadXSL();

}

OK了,我们设计好了顶级父类,子模块可以从此类继承下来,只需要实现 loadXML 和 loadXSL 方法!

其中 XML 由逻辑过程得出,XSL直接加载对应的模板文件即可。

为了描述的形象一点,我用一个网站的首页和用户消息中心来举例!

首先我们创建一个XML模板,这个模板文件把可能出现的数据都包含在里面,并按模块按深度设计好,假设如下:

CODE:

<?xml version="1.0" encoding="gb2312"?>

<l2p>

  <!-- 全局数据:网站大部分模块、页都会使用到的数据 -->

  <global>

    <title>网站标题</title>

  </global>

  <!-- 关于:这里可以随便按习惯放一点内容;如:作者、XML模板版本、联系方法等等 -->

  <about>

    <author>terry39</author>

    <QQ>1112114</QQ>

    <MSN> [email][email protected][/email] </MSN>

    <version>1.0</version>

  </about>

  <!-- 假设我们的模块都会显示菜单 -->

  <menu>

    <item id="0">

        <url>菜单的URL</url>

        <caption>菜单的标题</caption>

    </item>

    <item id="1">

        <url>菜单的URL</url>

        <caption>菜单的标题</caption>

    </item>

    <item id="3">

        <url>菜单的URL</url>

        <caption>菜单的标题</caption>

    </item>

  </menu>

  <!-- 首页模块显示:新闻、最新产品 -->

  <index>

    <news>

        <item id="0">

          <url>新闻的URL地址</url>

          <subject>菜单的标题</subject>

        </item>

        <item id="1">

          <url>新闻的URL地址</url>

          <subject>菜单的标题</subject>

        </item>

        <item id="2">

          <url>新闻的URL地址</url>

          <subject>菜单的标题</subject>

        </item>

    </news>

    <product>

        <item id="0">

          <url>产品URL地址</url>

          <product_name>产品名称</product_name>

        </item>

        <item id="1">

          <url>产品URL地址</url>

          <product_name>产品名称</product_name>

        </item>

        <item id="2">

          <url>产品URL地址</url>

          <product_name>产品名称</product_name>

        </item>

    </product>

  </index>

  <!-- 站内短信模块 -->

  <message>

    <!-- 当前是 INBOX -->

    <messagebox>inbox<messagebox>

    <!-- 要显示的消息列表 -->

    <message>

        <item id="0">

          <url>...</url>

          <title>...</title>

        </item>

        <item id="1">

          <url>...</url>

          <title>...</title>

        </item>

        <item id="2">

          <url>...</url>

          <title>...</title>

        </item>

    </message>

    <!-- 当前是第N页 -->

    <page>1</page>

    <!-- 总页数 -->

    <pagecount>2</pagecount>

    <!-- 每页显示数 -->

    <pagesize>3</pagesize>

  </message>

</l2p>

大家可能奇怪为什么都是

CODE:

  <item id="n"></item>

  <item id="n+1"></item>

  ...

的数据格式,而不是直接

CODE:

  <message></message>

  <message></message>

  ...

在PHP里最方便操作的是数组,所以我选择在模块中都直接操作数组,生成一个树型的数组,然后由数组在 loadXML() 方法里转换成XML

大家看一下这个 array2xml 函数

CODE:

  public static function array2xml($array){

    $xmlText = "";

    foreach($array as $key => $value){

        is_numeric($key) && $key = "item id='{$key}'";

        $xmlText .= "<{$key}>";

        $xmlText .= (is_array($value) ? self::array2xml($value) : "<![CDATA[{$value}]]>");

        list($key,) = explode(" ", $key);

        $xmlText .= "</$key>/n";

    }

    return $xmlText;

  }

所以 loadXML 就可以写成:

CODE:

  public function loadXML(){

    $xmlText = self::array2xml($this->dataTree);

    $xmlText = "<?xml version='1.0' encoding='gb2312'?>/n{$xmlText}";

    $xml = new DOMDocument();

    $xml->loadXML($xmlText);

    return $xml;

  }

其中我注释了如下这段,大家看看是什么作用:

CODE:

XML模板设计好后,我们就可以设计如何显示这些数据了 ---- 模板设计!在这里我就不继续讨论XSL的设计了,用 Dreamweaver 可以很方便的以做网页的方式来设计XSL格式的文件;

在用 DW 设计XSL文件时,我们的XML模板就起作用了,网页美工设计人员可以很方便的设计出符合规范,并美观的 XSL 模板文件。我传了一个图,大家仔细看一看便明白!(如果你还不会制作网页,那就不适合看此文了 ^^)