我希望有一个像这样的foreach任务,它迭代目录"A"中的所有文件/目录 -
<foreach param="dirname" absparam="absname" target="subtask">
<fileset dir="${dir.destination}/${dir.subdir}/">
<type type="file" />
</fileset>
</foreach>
Run Code Online (Sandbox Code Playgroud)
目标"子任务"应该检查文件/文件夹的对应物是否存在于另一个目录"B"中(我基本上比较目录A和B),如果不是,则返回以下任一项 -
以下是一些参考代码 -
<target name="subtask">
<if>
<filesmatch file1="${file1}" file2="${file2}"/>
<then>
Return false. But how?
</then>
<else>
Return true of name of the file. How?
</else>
</if>
</target>
Run Code Online (Sandbox Code Playgroud)
注意 - 如果可以在不调用目标的情况下完成此操作,则可以.我不确定逻辑是否适合在foreachtask本身.在phing文档中找不到任何这样的东西.
基本上,我应该在循环结束时获得目录B中不存在的文件名列表.
你也可以阅读我的这个问题,如果你能给出一些指示以某种方式解决问题.
更新
重述这个问题,因为我觉得问题描述不清楚.该phing文件说,一个目标没有返回值-
目标是在项目中分配了唯一名称的项目组件(但不是其他目标)的集合.目标通常执行特定任务 - 或调用执行特定任务的其他目标 - 因此目标有点像函数(但目标没有返回值).
我不明白它为什么这么设计.有了这个赏金,我想知道除了必须在PHP中定义自己的自定义任务,然后设置属性之外是否还有一些解决方法 -
$this->getProject()->setNewProperty('modifiedElements', implode("\n\n",$modifiedElementsArray));
Run Code Online (Sandbox Code Playgroud)
可以在构建文件中访问
我有一个目标,检查我的生产代码库是否与预期的git版本有任何差异 -
<target name="compare_prod_with_expected_revision">
<input propertyname="box.git_version">
Enter git version of the production codebase:
</input>
<exec command="git reset --hard ${box.git_version}" dir="${dir.scratchpad}" />
<!-- Scratchpad brought to revision ${box.git_version} -->
<echo>Verifying whether production is at revision ${box.git_version}..</echo>
<exec command="diff -arq --exclude='.git' ${dir.scratchpad}/${dir.subdir} ${dir.destination}/${dir.subdir}" outputProperty="diffList"/><!-- #TODO ignore.swp files in this step. Diff says .swp files present in production code. But doing ls -a there does not show the same. -->
<php function="strlen" returnProperty="productionDeviationFromExpectedBranch"><!-- #TODO - find how to not show this step during build process. Put it in a target and set hidden="true" -->
<param value="${diffList}"/>
</php>
<if>
<equals arg1="${productionDeviationFromExpectedBranch}" arg2="0" />
<then>
<echo>Verified production is at revision ${box.git_version}</echo>
</then>
<else>
<echo>Differences - </echo>
<echo>${diffList}</echo>
</else>
</if>
</target>
Run Code Online (Sandbox Code Playgroud)
现在,我想要phingcall这个目标,并希望访问它设置的一些属性.
我想我理解你的目的,同时我觉得你选择的不是这样做的最佳工具.
正如您在问题中提到的,关于phing的官方文档清楚地表明了任务(目标):
目标是在项目中分配了唯一名称的项目组件(但不是其他目标)的集合.目标通常执行特定任务 - 或调用执行特定任务的其他目标 - 因此目标有点像函数(但目标没有返回值).
目标应该是应用程序的组件,它们执行特定任务,原子任务.它可以是初始化任务,配置获取,编译步骤,资产准备和转储,部署任务,清理任务等.标准意义上没有目标返回的"输出",但目标执行的结果是成功执行本身:成功或失败.
人们不应该试图将太多的逻辑放在这样的项目目标中,因为它不打算进行复杂的计算,做出重大的逻辑决策等等.我的意思是,Phing可以做到,这样的事情是可能的,但这种设置会体积庞大,难以理解,难以扩展/重新考虑因素.
使用Phing,您可以轻松定义条件执行和逻辑流程的分支,您可以定义任务(依赖项)的执行顺序 - 这就是简洁和优雅的原因.保持目标尽可能简单,将项目拆分为完成的小型逻辑任务.
基于我一直在使用的项目,最大的目标可能是初始化阶段和配置提取.这是一些例子,为了理解它可能包含的内容,我从实际项目中获取了它:
<target name="init_configuration">
<echo msg="Define initial configuration for the deployment..." />
<if>
<not>
<isset property="host" />
</not>
<then>
<property name="host" value="dev" override="true" />
<echo message="The value of hostname has been set to ${host}" />
</then>
<else>
<echo message="The value of hostname is ${host}" />
</else>
</if>
<if>
<not>
<isset property="version" />
</not>
<then>
<property name="version" value="1.0.0" override="true" />
<echo message="The value of version has been set to ${version}" />
</then>
<else>
<echo message="The value of version is ${version}" />
</else>
</if>
<property name="host_credital_file" value="config/hosts/${host}.properties" />
<property file="${host_credital_file}" />
<available file="${host_credital_file}" property="hostfilefound" value="true"/>
<fail unless="hostfilefound" message="Missing Hostfile configuration file (${host_credital_file})!" />
<echo msg="Configuration is done" />
</target>
Run Code Online (Sandbox Code Playgroud)
其他目标非常简单,它们通常是1-5行,只做小目的,小任务.这可能是与Phing合作时的最佳建议.
你试图把Phing放在肩上的逻辑是可能的,但是会非常笨重.
考虑一下:在您的示例中,使用简单的bash脚本可以更快,更容易,更可读.甚至可以在PHP中编写小型CLI实用程序,它可以优雅而快速地完成工作.之后在Phing中你将离开参数目标,它将从CLI执行这个"修订差异脚本".
Phing是设计用途的绝佳工具,但它不能成为各种用途的最佳选择.只是不要把责任和逻辑放在其中.
作为一种解决方法,对于更复杂的事情,最好将Phing与专门的东西结合起来:bash脚本,PHP CLI,nodeJS(+ Grunt,Gulp等)......以及稍后添加Phing目标的调用.