第五章 Project Components 本章的目的是让你熟悉构建文件(buildfile)的基本组成。 更多参考信息,可以参看附录B(Core Tasks),附录D(core Types)以及附录H(Project Components)
Projects 在phing的构建文件(buildfile)中,有且只能有一个Project的定义;<project>标签是构建文件的根元素,这意味着文件中其他元素必须包含在<project>之中。
<?xml version="1.0"?>
<project name="test" description="Simple test build file" default="main" >
<!-- Everything else here -->
<project>
上面这段代码给出了一个简单的<project>的例子,它包含了项目中用到的常见属性。name和description属性的含意是显而易见的;default属性指明在没有指定target的情况下,默认执行的target(关于target将在下文中详细描述)。
Version
从2.4.2版本开始,phing允许在<project>标签中包含phingVersion属性。这个属性允许你定义用于执行当前构建文件的最低phing版本。
例:
<?xml version="1.0"?>
<project name="test" phingVersion="2.4.2" >
<!-- Everything else here -->
<project>
Project Components in General
项目组件(project components)是所有可以出现在项目中的元素,比如targets, tasks,types等等。项目组件可以包含属性及嵌套标签。属性仅包含简单值,比如字串,整数等等。嵌套元素可以是复杂的Phing types,也可以是包含着一系统键值对的类。
比如:
<fileset dir="/etc" >
<include name="httpd/**" />
<include name="php.ini" />
</fileset>
嵌套元素必须是项目组件支持的类。根据上下文的不同,同样的嵌套标签可能有不同的含意。比如,<pingcall>中的<param.../>和<xsltfilter>中的<param.../>就是不同的。前者设定项目特性,后者设定XSLT参数。
Targets
targets是项目组件(project components)的集合,project中,每个target有一个唯一的名字。一个target执行一个特定的任务,或者调用其它的target。从这个角度说,target有点像函数(但是target没有返回值)。
一个target可能依赖其它target。比如,如果target A依赖target B,则当A被执行时,target B将先于A被执行。phing会自动解析这些依赖关系。注意不要出现循环引用的情况,比如:target A依赖target B,target B又依赖target A。
例:
<target name="othertask" depends="buildpage" description="Whatever">
<!-- Task calls here -->
</target>
<target name="buildpage" description="Some description">
<!-- Task calls here -->
</target>
当执行othertask时,phing会检查依赖关系,并优先执行buildpage。
Tasks
task是可以执行的行为个体。比如task可以拷贝文件,可以创建目录,tar某个目录下的文件。task也可能很复杂,比如XsltTask,拷贝文件并通过XSLT传输;SmartyTask,可以像smarty模板那样工作;CreoleTask可以执行sql语句。详细信息可参见附录B(Core Tasks for descriptions of Phing tasks.)。
Task支持以下两种参数形式:
1.简单参数(比如字串),以xml属性的形式传递
2.复杂参数,以嵌套标签形式传递
简单参数基本都是字串。比如,如果你将"A simple string."作为参数传值,它将被作为字符串赋值或访问。
注意:
有些特定的值不会被映射为字串,而是布尔值。比如true,false,yes,no,on以及off,会被转换为对应的布尔值true/false。
例如:
<property name="myprop" value="value" override="true"/>
一些task支持以复杂数据类型作为参数。这些参数以嵌套标签(nested tags)的形式传递。例:
<copy>
<fileset dir=".">
<include name="**" />
</fileset>
</copy>
上例中,我们向CopyTask传了以一复杂参数,Fileset。注意,嵌套标签的名字取决于所要执行的task。task参数支持默认的ping类型,也可以引入其它类型,比如键值对。
参见附录B(Core Tasks),可以了解更多系统task以及它们支持的参数。
Types
基础
除了简单参数(字串,整数,布尔)外,我们还可以向task传递更复杂Phing类型参数。如上文所述,它们可以以嵌套标签的形式传递。
比如:
<task>
<type />
</task>
<!-- or: -->
<task>
<type1>
<subtype1>
<!-- etc. -->
</subtype1>
</type1>
</task>
注意,type可以由多级嵌套标签组成。
Referencing Types
事件定义好自己的类型,并赋予一个id。之后就可以通过这个id引用此类型。
例:
<project>
<fileset id="foo">
<include name="*.php" />
</fileset>
<!-- Target that uses the type -->
<target name="foo" >
<copy todir="/tmp">
<fileset refid="foo" />
</copy>
</target>
</project>
就像你所看到的,type实例被定义并设定了id属性,之后传给CopyTask的仅是一个空的fileset,但包含了refid属性,用于引用之前定义的type。
基本的Types
下面一小节将带你快速浏览下基本的Phing类型。更多信息可参考附录D(Core Types)。
FileSet
FileSets是一组文件。你可以使用文件名或模式(pattern)在FileSet中包含或排除特定的文件。模式的使用将在下文中讲解。先看一个例子:
<fileset dir="/tmp" id="fileset1">
<include name="sometemp/file.txt" />
<include name="othertemp/**" />
<exclude name="othertemp/file.txt" />
</fileset>
<fileset dir="/home" id="fileset2">
<include name="foo/**" />
<include name="bar/**/*.php" />
<exclude name="foo/tmp/**" />
</fileset>
模式的使用十分简单:如果你仅需要匹配文件或目录名的一部分,使用*。如果你想包含所有文件和目录,使用**。
FileList
FileList,和FileSet很像,是一系列文件集合;不同的是,FileList精确的定义了一组文件,这些文件不一定要在文件系统中存在。
除此之外,FileList还允许你定义文件处理顺序。有时,你可能想以特定的顺序处理一批文件,比如你想使用<append>任务连接一些文件。
例:
<filelist dir="base/" files="file1.txt,file2.txt,file3.txt"/>
<!-- OR: -->
<filelist dir="basedir/" listfile="files_to_process.txt"/>
FilterChains and Filters
FilterChains很像Uinx的管道。
cat foo | head -n10 | grep blee > bar
类似上面这段脚本的功能使用上文说到的task以及type是不可能实现的。因此,我们需要FilterChains!它十分的强大。它模仿的Unix的管道,为那些支持FilterChains的task提供文件流操作。
FilterChains的使用也非常简单:将filterchain传给支持它的task,在filterchain中增加独立的filter即可。执行task的过程中,filters会按照其在xml中出现的顺序依次作用于待处理的文件内容。
例:
<filterchain>
<replacetokens>
<token key="BC_PATH" value="${top.builddir}/"/>
<token key="BC_PATH_USER" value="${top.builddir}/testsite/user/${lang}/"/>
</replacetokens>
<filterreader classname="phing.filters.TailFilter">
<param name="lines" value="10"/>
</filterreader>
</filterchain>
上例中的filter chain会将所有的BC_PATH和BC_PATH_USER替换成相应value所指定的值(第4,5行)。另外,将返回文件的最后10行。
注意,上面FilterChain中的filter使用的简化写法,它们都有与之对应的长的通用写法。大部分的filter兼容两种形式:
<replacetokens>
<token key="BC_PATH" value="${top.builddir}/"/>
<token key="BC_PATH_USER" value="${top.builddir}/testsite/user/${lang}/"/>
</replacetokens>
<!-- OR: -->
<filterreader classname="phing.filters.ReplaceTokens">
<param type="token" name="BC_PATH" value="${top.builddir}/"/>
<param type="token" name="BC_PATH" value="${top.builddir}/testsite/user/${lang}/"/>
</filterreader>
File Mappers
Mappers是更换文件名的强大工具。
使用Mapper时,你必须指定的一个匹配模式和一个替换模式,前者用于匹配文件,后者用于描述匹配到的文件如何转换。最简单的mapper形式和DOS的copy命令几乎一样:
Dos命令:
copy *.bat *.txt
对应Phing中的glob mapper:
<mapper type="glob" from="*.bat" to="*.txt"/>
Phing支持在mapper中使用正则:
<mapper type="regexp" from="^(.*)\.conf\.xml$$" to="\1.php"/>
下面的例子展现了如何在构建文件中使用Mapper。这个例子包含了本章所讲到的其它内容,比如FilterChains和FileSets。即使你无法理解它们,也不要担心。因为我们的重点是让你知道:Mappers也是一种type,它可以在支持它们的task中使用。
<copy>
<fileset dir=".">
<include name="*.ent.xml" />
</fileset>
<mapper type="regexp" from="^(.*)\.ent\.xml$" to="\1.php"/>
<filterchain>
<filterreader classname="phing.filters.XsltFilter">
<param name="style" value="ent2php.xsl" />
</filterreader>
</filterchain>
</copy>
更多信息请参考附录F(Core Mappers)。