27、PHP开发中的持续集成与XML解析

PHP开发中的持续集成与XML解析

1. 持续集成概述

持续集成(Continuous Integration,CI)旨在实现代码测试的频繁自动化运行,这有助于实现快速、稳定的发布周期。CI服务器会在代码仓库发生变更(如代码提交)、按定时间隔(如每小时)或按需执行一系列预定义的构建任务,像代码部署、代码测试或生成分析报告等。

以下是一个可通过构建系统执行的多步骤任务示例:
1. 从源代码控制中检出当前版本的代码。
2. 从网站获取第三方库的最新版本。
3. 对程序进行静态分析。
4. 对程序中的PHP代码进行单元测试。

若要发布程序的新版本,在单元测试成功后,还可设置额外的构建步骤:
1. 混淆PHP代码。
2. 创建WAR文件工件。
3. 从版本控制系统中获取修订号。
4. 从数据库或文件中读取当前发布版本。
5. 创建此修订版本与上一发布版本之间的补丁。
6. 将构建标记为发布版本。
7. 在发布版本数据库中插入新记录或更新当前发布版本文件。
8. 将WAR文件部署到公共可访问的服务器。

手动执行上述步骤不仅耗时,还容易出错。而使用CI,可在每次提交后自动执行这些步骤,也可仅为特定构建标记额外的八个部署步骤。

2. 持续集成服务器

PHP开发中,有两款优秀的免费CI服务器:Jenkins和phpUnderControl。Jenkins是Hudson项目的分支,是全球最常用的CI系统之一;phpUnderControl则与CruiseControl CI框架集成。二者均用Java编写,支持多种构建系统和语言,并提供众多附加插件。这里以Jenkins为例进行介绍。

Jenkins、phpUnderControl和CruiseControl的官网如下:
- Jenkins:http://jenkins-ci.org/
- phpUnderControl:http://phpundercontrol.org/
- CruiseControl:http://sourceforge.net/projects/cruisecontrol/files/

CI服务器使用的工具主要有:
1. 版本控制
2. 单元测试与代码覆盖
3. 静态分析
4. 构建自动化

3. 版本控制

版本控制,也称为源代码控制或修订控制,是程序员必备的重要工具。它如同集数字磁带录音机和混音器功能于一体的设备,能回放现有内容、添加新内容、回退到特定位置、分支到不同轨道,还能混合不同部分。不过,有时各部分可能会冲突,需要进行编辑以使其协调工作。

流行的版本控制系统有Subversion(SVN),以及新兴的分布式版本控制系统,如Git和Mercurial,它们在开发生态系统中得到了广泛支持。

这些版本控制系统的在线文档链接如下:
- Subversion:http://svnbook.red-bean.com/
- Git:http://gitref.org/
- Mercurial:http://hgbook.red-bean.com/

4. 静态分析

静态分析工具通过指标检查代码,可揭示以下有用信息:
- 计算复杂度级别(越高越差)
- 依赖关系(越少越好)
- 最佳实践建议
- 代码风格规范遵循情况
- 问题代码和潜在bug检测
- 重复代码显示
- 文档生成

多数PHP静态分析工具以IDE插件或PEAR包的形式提供,以下是按类别划分的部分现有工具:
| 类别 | 工具名称 | 链接 |
| ---- | ---- | ---- |
| 遵循代码规范 | PhpCheckstyle | http://code.google.com/p/phpcheckstyle/ |
| 遵循代码规范 | PHP Code Sniffer | http://pear.php.net/package/PHP_CodeSniffer/ |
| API生成 | PHP Documentor | http://www.phpdoc.org/ |
| 代码质量指标 | PHP Lines of Code | https://github.com/sebastianbergmann/phploc |
| 代码质量指标 | pdepend | http://pdepend.org/ |
| 代码质量建议 | PHP Copy/Paste Detector | https://github.com/sebastianbergmann/phpcpd |
| 代码质量建议 | phpmd PHP mess detector | http://phpmd.org/ |
| 代码质量建议 | phantm - PHp ANalzer for Type Mismatches | https://github.com/colder/phantm |
| 代码质量建议 | padawan | https://github.com/mayflowergmbh/padawan |
| 高亮显示 | phpcb | https://github.com/mayflowergmbh/PHP_CodeBrowser |
| 安全 | PHP Security Audit Tool | http://sourceforge.net/projects/phpsecaudit/ |

5. 构建自动化

为自动化重复任务,可使用Apache Ant、Maven或Phing等构建系统。这些构建系统基于XML文件,典型的构建文件包含一个或多个目标,每个目标又包含子任务,可用于添加或删除文件、从仓库检出文件、运行单元测试、进行静态分析、生成文档等。

以下是一个简单的构建文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<project default="testAutomate">
    <target name="testAutomate">
        <echo msg="Making directory ./foobar" />
        <mkdir dir="./foobar" />
    </target>
</project>

此示例中有一个构建目标“testAutomate”,该目标会输出一条消息并创建一个目录。构建文件可包含多个目标,且可能会变得非常复杂。

6. Jenkins服务器设置

Jenkins布局直观,拥有庞大的支持社区,既强大又易于使用,提供了良好的GUI和命令行脚本。设置Jenkins与PHP的基本步骤如下:
1. 从http://jenkins-ci.org/ 下载并安装Jenkins,具体安装过程因操作系统和版本而异,可在https://wiki.jenkins-ci.org/display/JENKINS/Home 获取扩展帮助。默认使用端口8080,可通过http://localhost:8080/dashboard 访问仪表盘。
2. 配置Jenkins插件,可使用Web界面或命令行工具,示例命令如下:

wget http://localhost:8080/jnlpJars/jenkins-cli.jar
java –jar jenkins-cli.jar –s http://localhost:8080 install-plugin checkstyle
java –jar jenkins-cli.jar –s http://localhost:8080 install-plugin clover
java –jar jenkins-cli.jar –s http://localhost:8080 install-plugin jdepend
java –jar jenkins-cli.jar –s http://localhost:8080 install-plugin pmd
java –jar jenkins-cli.jar –s http://localhost:8080 install-plugin phing
java –jar jenkins-cli.jar –s http://localhost:8080 install-plugin xunit
java –jar jenkins-cli.jar –s http://localhost:8080 safe-restart
  1. 升级PHP pear包,可能需要发现新的PEAR频道并安装相关包,示例命令如下:
pear channel-discover pear.pdepend.org
pear channel-discover pear.phpmd.org
pear channel-discover pear.phpunit.de
pear channel-discover components.ez.no
pear channel-discover pear.symfony-project.com
pear install pdepend/PHP_Depend
pear install phpmd/PHP_PMD
pear install PHPDocumentor
pear install PHP_CodeSniffer
pear install phpunit/phpcpd
pear install –alldeps phpunit/PHP_CodeBrowser
pear install –alldeps phpunit/PHPUnit

若安装过程中出现错误,可能需要更改pear配置,例如:

pear config-get data_dir
pear config-set data_dir “C:\xampp\php\pear\data”
pear config-set doc_dir “C:\xampp\php\pear\docs”
pear config-set test_dir “C:\xampp\php\pear\tests”
  1. 创建构建文件,可参考Bergmann编写的实用脚本,通过pear包管理器安装:
pear install phpunit/ppw

或从https://github.com/sebastianbergmann/php-project-wizard 在线获取。
5. 创建新的Jenkins作业。

下面是Jenkins设置流程的mermaid流程图:

graph LR
    A[下载并安装Jenkins] --> B[配置Jenkins插件]
    B --> C[升级PHP pear包]
    C --> D[创建构建文件]
    D --> E[创建新的Jenkins作业]
7. XML概述

可扩展标记语言(XML)是用于数据存储和传输的强大工具。用XML编写的文档能被普遍理解和交换,其作为全球标准的实用性不容小觑。XML广泛应用于现代文字处理文档、SOAP和REST Web服务、RSS提要以及XHTML文档等。

XML允许定义使用任意标签元素和属性的文档,在文本编辑器中查看XML文档时,会发现它与HTML相似,因为二者都是标记语言,具有分层结构的标签内容。XML文档的分层结构呈树状,有一个根元素(标签)作为主干,子元素从根元素分支出来,进一步的后代元素从其父元素分支出来。也可以将XML文档按顺序视为一系列离散事件,但按顺序查看元素时,虽然无需了解整个文档的含义,但查找元素会更困难。

XHTML是XML的一个具体应用,它与HTML使用相同的标签,但更严格,有以下额外要求:
- 标签区分大小写,XHTML元素名称必须始终为小写。
- 单元素(如 <br> )需要关闭,应使用 <br />
- 实体 & < > ' " 需要分别转义为 &amp; &lt; &gt; &apos; &quot;
- 属性需要用引号括起来,例如 <img src=dog.jpg /> 是非法的,而 <img src="dog.jpg" /> 是合法的。

解析XML可使用基于树的模型或事件驱动模型。基于树的模型(如SimpleXML和DOM使用的模型)将HTML和XML文档表示为元素树,并将整个文档加载到内存中。除根元素外,每个元素都有一个父元素,元素可以包含属性和值。事件驱动模型(如Simple API for XML,SAX)一次只读取部分XML文档。对于大文档,SAX更快;对于非常大的文档,它可能是唯一可行的选择。然而,基于树的模型通常更易于使用和直观,并且某些XML文档需要一次性加载整个文档。

一个基本的XML文档示例如下:

<animal>
    <type id="9">dog</type>
    <name>snoopy</name>
</animal>

此文档中,根元素是 <animal> ,有两个子元素 <type> <name> <type> 元素的值是 “dog”, <name> 元素的值是 “snoopy”。 <type> 元素有一个属性 id ,其值为 “9”。此外,每个开始标签都有匹配的结束标签,属性值用引号括起来。

8. XML模式

XML模式为XML文档提供了额外的约束,例如特定元素是可选的还是必须包含的、元素的可接受值和属性以及元素的放置位置等。

如果没有模式,可能会出现无意义的数据,例如以下示例:

<animals>
  <color>black</color>   
  <dog>
    <name>snoopy</name>
    <breed>
      <cat>  
        <color>brown</color>
        <breed>tabby</breed>
      </cat>
      beagle cross
    </breed>
 </dog>
 <name>teddy</name>   
</animals>

从人类的角度来看,这个文档没有意义,因为猫不能是狗的一部分, color name 不是动物,应该包含在狗或猫元素中。但从机器的角度来看,这是一个完全有效的文档。模式可以告知机器如何强制执行数据布局,这种额外的严格性确保了文档中数据的完整性。例如,可以明确规定 <cat> 标签不能放在 <dog> 标签内, <name> <color> 标签只能直接放在 <cat> <dog> 标签内。

常见的三种模式生成语言是文档类型定义(DTD)、XML模式和RELAX NG(REgular LAnguage for XML Next Generation)。在使用时,需要在文档开头声明所使用的模式,示例如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
9. SimpleXML解析XML

SimpleXML可以轻松地将XML存储为PHP对象,反之亦然,它简化了XML结构的遍历和特定元素的查找。SimpleXML扩展需要PHP 5或更高版本,并且默认启用。

9.1 从字符串解析XML

以下是一个将字符串中的XML加载到SimpleXMLElement对象并遍历结构的示例:

<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = <<<THE_XML
  <animal>
    <type>dog</type>
    <name>snoopy</name>
  </animal>      
THE_XML;
$xml_object = simplexml_load_string($xml);
foreach ($xml_object as $element => $value) {  
    print $element . ": " . $value . "<br/>";
}
?>

加载XML字符串后, $xml_object 位于根元素 <animal> 。文档表示为SimpleXMLElement对象,因此可以使用 foreach 循环遍历子元素。上述代码的输出如下:

type: dog
name: snoopy

再看一个更复杂的示例:

<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = <<<THE_XML
<animals>
  <dog>
    <name>snoopy</name>
    <color>brown</color>
    <breed>beagle cross</breed>
  </dog>
  <cat>
    <name>teddy</name>
    <color>brown</color>
    <breed>tabby</breed>
  </cat>
  <dog>
    <name>jade</name>
    <color>black</color>
    <breed>lab cross</breed>
  </dog>
</animals>
THE_XML;
$xml_object = simplexml_load_string($xml);
foreach($xml_object->dog as $dog){
   print $dog->name."<br/>";
}
?>

此示例大部分使用PHP heredoc语法以可读的方式加载字符串,实际用于查找元素值的代码只有几行。SimpleXML能够智能地遍历所有 <dog> 标签,即使 <dog> 标签之间有 <cat> 标签。上述代码的输出如下:

snoopy
jade
9.2 从文件解析XML

当加载XML时,如果文档无效,PHP会给出有用的警告消息,提示需要关闭标签或转义实体,并指出错误的行号。例如:

Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser error : attributes construct error in E:\xampp\htdocs\xml\animals.php on line 29

下面是从文件加载XML的示例,首先是示例XML文件 template.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <body>
        <div id="header">
            header would be here
        </div>
        <div id="menu">
            menu would be here
        </div>
        <div id="main_content">
            <div id="main_left">
                left sidebar
            </div>
            <div id="main_center" class="foobar">
                main story
            </div>
            <div id="main_right">
                right sidebar
            </div>
        </div>
        <div id="footer">
            footer would be here
        </div>
    </body>
</html>

然后是查找特定元素值的PHP代码:

<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = simplexml_load_file("template.xhtml");
findDivContentsByID($xml, "main_center");
function findDivContentsByID($xml, $id) {
  foreach ($xml->body->div as $divs) {
      if (!empty($divs->div)) {
          foreach ($divs->div as $inner_divs) {
              if (isElementWithID($inner_divs, $id)) {
                  break 2;
              }
          }
      } else {
          if (isElementWithID($divs, $id)) {
              break;
          }
      }
  }
}
function isElementWithID($element, $id) {
    $actual_id = (String) $element->attributes()->id;
    if ($actual_id == $id) {
        $value = trim((String) $element);
        print "value of #$id is: $value";
        return true;
    }
    return false;
}
?>

上述代码会查找 <body> 元素的所有 <div> 元素以及这些 <div> 元素的直接子 <div> 元素,然后将每个匹配的 <div> 元素的 id 属性与搜索值 “main_center” 进行比较。如果相等,则输出值并跳出循环。脚本的输出如下:

value of #main_center is: main story
9.3 使用XPath查找元素

XPath是SimpleXML库和PHP DOM库的一部分,可用于简化元素的查找。以下是使用XPath的示例:

<?php
error_reporting(E_ALL);
$xml = <<<THE_XML
  <animal>
    <type>dog</type>
    <name>snoopy</name>
  </animal>      
THE_XML;
$xml_object = simplexml_load_string($xml);
$type = $xml_object->xpath("type");
foreach($type as $t) {
    echo $t."<br/><br/>";
}
$xml_object = simplexml_load_string($xml);
$children = $xml_object->xpath("/animal/*");
foreach($children as $element) {
    echo $element->getName().": ".$element."<br/>";
}
?>

上述代码的输出如下:

dog
type: dog
name: snoopy

在上述代码的第一部分,使用XPath选择器 “type” 选择 <animal> <type> 内部元素,返回一个匹配XPath查询的SimpleXMLElement对象数组。第二部分使用XPath选择器 “/animal/*” 选择 <animal> 的所有子元素,其中星号是通配符。由于 xpath() 调用返回SimpleXMLElement对象,因此还可以使用 getName() 方法输出元素名称。

下面是一个匹配特定子元素并查找其父元素的示例:

<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = <<<THE_XML
<animals>
  <dog>
    <name>snoopy</name>
    <color>brown</color>
    <breed>beagle cross</breed>
  </dog>
  <cat>
    <name>teddy</name>
    <color>brown</color>
    <breed>tabby</breed>
  </cat>
  <dog>
    <name>jade</name>
    <color>black</color>
    <breed>lab cross</breed>
  </dog>
</animals>
THE_XML;
$xml_object = simplexml_load_string($xml);
$names = $xml_object->xpath("*/name");
foreach ($names as $element) {
    $parent = $element->xpath("..");
    $type = $parent[0]->getName();
    echo "$element ($type)<br/>";
}
?>

总结

我们介绍了有助于创建高质量PHP代码的三种开发实践:重构、单元测试和持续集成,以及XML的相关知识。持续集成可以自动化代码测试和构建任务,提高开发效率和代码质量;XML作为数据存储和传输的标准,SimpleXML则为PHP开发者提供了便捷的XML处理方式。开发者应不断追求代码的高质量保证,关注新的技术和工具。

下面是SimpleXML解析XML的流程mermaid流程图:

graph LR
    A[选择解析方式] --> B{从字符串解析?}
    B -- 是 --> C[使用simplexml_load_string]
    B -- 否 --> D[使用simplexml_load_file]
    C --> E[遍历或查找元素]
    D --> E
    E --> F{使用XPath?}
    F -- 是 --> G[使用xpath方法查找元素]
    F -- 否 --> H[使用常规方法查找元素]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值