Archive

Posts Tagged ‘Phing’

Integrating Phing With PHPUnit

January 16th, 2009 Tech No comments

PHPUnit is a unit testing framework, written in PHP, and which is used to test PHP code. You can integrate the testing that PHPUnit does into Phing. You might want to use Phing to create a nightly build that contains the latest version of your program. The last thing you want is Phing to create a nightly build that is riddled with errors.

The way around this is to use PHPUnit to test our code whilst we are running Phing. If any tests fail then Phing will not finish the build.

Create a target at the top of your build.xml file and make sure it is run first. Then add the following code to the target, This will use PHPUnit to test your code.

<phpunit haltonfailure="true" haltonerror="true">
  <batchtest>
    <fileset dir="tests">
      <include name="**/*Test*.php"/>
    </fileset>
  </batchtest>
</phpunit>

The phpunit element contains an element called batchtest, which can contain one or more fileset elements. It is the files defined by the fileset elements that define which files are to be used in the testing. The code above includes all PHP files that have the word Test in their name.

The phpunit element contains two attributes called haltonfailure and haltonerror. These attributes will cause the build to exit if any errors or failed tests are found during the testing.

Create Compressed Files With Phing

January 15th, 2009 Tech 1 comment

Building your projects into directories is nice, but distributing these projects is difficult if you have to build the compressed files yourself. Phing has the ability to create zip and tar files using simple commands.

The most convenient way of using the tar and zip commands is by using a fileset. But rather than use the fileset that was used to copy the files into the build directory it is best to create a separate fileset that is used to compress the contents of the build directory.

<fileset dir="./" id="zipFiles">
<include name="myProject_build/**" />
</fileset>

To compress the files into a tar use the tar element. This accepts two parameters, the destination file (called destfile) and the compression to use (called compression). The compression attribute can take one of three values, these are gzip, bzip2 and none. Using none will not run any compression algorithms on the files. The following example will create a file called myProject.tar in the current directory, which contains all of the files and directories from the myProject_build directory.

<tar destfile="myProject.tar" compression="gzip">
<fileset refid="zipFiles" />
</tar>

To compress the files into a zip file you need to use the zip element. This works in exactly the same way as the tar element, except it doesn’t have a compression attribute.

<zip destfile="myProject.zip">
<fileset refid="zipFiles" />
</zip>

The tar element works very well and the file created was as expected, but I had a little bit of trouble with the zip element. I am using Windows XP to run phing and the file that was created was blocked by Windows for having odd content. After I figured out how to open it I realized that phing had used the full path to the build folder. So rather than the zip file containing a folder called myProject_build, it contained the following folder structure, with the correct files included in the end directory.

C:\dev\tests\phing\myProject_build

Has anyone else seen this? I would be grateful for any help on the subject.

You can also use the zip and tar elements without the fileset element by using the basedir attribute. By setting the basedir you are telling phing to use everything in that directory and every sub directory.

<tar destfile="phing.tar" basedir="." compression="gzip"/>

There is a warning on the phing website that states using basedir and fileset simultaneously can result in strange contents in the archive. So I would suggest using one or the other.

Categories: PHP Tags: , , , , , ,

Create A File Or Directory With Phing

January 14th, 2009 Tech No comments

After following the last post on deleting files and directories in Phing you might now be wondering if you can create things as well. The answer is yes.

To create a directory with Phing you need to use the mkdir element. The dir attribute is used to give the name of the directory to be created. The following example will create a directory called myProject_build in the current working directory (ie. where you are running phing from).

<mkdir dir="myProject_build" />

That is about as complicated as the mkdir element gets, although you can also pass a parameter to the dir attribute.

<mkdir dir="${projectDirectory}" />

To create a file with Phing you need to use the touch element. The file attribute is used to give the name of the file being created.

<touch file="README.txt" />

You can optionally include one of two date attributes in the touch element. This are datetime (as a date string) and millis (as an integer timestamp) which set the creation timestamp of the file. If you don’t include either of these attributes then the current time stamp (ie. now) will be used instead.

Categories: PHP Tags: , , , , , ,

Deleting Directories With Phing

January 13th, 2009 Tech No comments

Although using Phing is mainly about copying files, you might also need to delete directories and files using the delete element. Remember that the default behavior of copy command copies files only if the source files are different from the destination files. A prudent approach might be to delete the build directory and then recreate it, ready for Phing to copy files into.

To delete a directory you need to use the dir attribute of the delete element, the delete element also accepts the file attribute to delete specific files. The following target will delete the directory myProject_build.

<target name="prepare">
<delete dir="myProject_build" />
</target>

The delete element can also accept a fileset element, which will delete multiple files. the following code will delete any php file from the myProject_build folder and from a sub folder called app.

<fileset dir="./" id="deleteFiles">
 <include name="myProject_build/*.php" />
 <include name="myProject_build/app/*.php" />
</fileset>
 
<target name="prepare">
  <delete>
    <fileset refid="deleteFiles" />
  </delete>
</target>

Remember when doing this to remove any dir or file attributes from the delete element as they can interfere with your fileset. Also, if you use a fileset be careful not to use the same fileset that copies the files into the build directory as the only thing you will accomplish is the deletion of your application. This is quite easy to do, I even did it whilst testing the previous example!

Categories: PHP Tags: , , , , , , ,

FilterChain Element In Phing

January 12th, 2009 Tech No comments

The FilterChain element is where the power of Phing really comes into its own. This element will allow you to change the contents of the files of a fileset. This can range from a simple stripping of comments, to replacing values and numerous other filters.

One of the simplest thing that can be done with filterset is to strip all comments from the files in question. Take the following PHP file with two comments.

<?php
/**
 *
 * This is a comment
 *
 *
 **/
echo 'Hello World!';
 
// another comment.

These comments can be stripped out of the file by using the stripphpcomments element. This is added to the copy element in the following way.

<?xml version="1.0"?>
<!-- build xml -->
 <project name="myProject" default="main">
 
 <fileset dir="./" id="myProjectFiles">
  <include name="**/*.php" />
  <exclude name="myProject_build/**" />
 </fileset>
 
 <target name="main">
  <copy todir="./myProject_build">
   <fileset refid="myProjectFiles" />
   <filterchain>
    <stripphpcomments />
   </filterchain>
   </copy>
 </target>
</project>

The PHP file now looks like this.

<?php
 
echo 'Hello World!';
 
 
 

Although this might be a nightmare to maintain it might be useful if reducing the size of your files is necessary. You might want to do this if you plan to sell your PHP software as it would make alteration by your customer a little bit more difficult.

Another use of the filterchain is to replace values within the code base. This is useful if you want to set a version number or a default database password. To replace a token with a value you need a property that can will store the value. You then need to go into your source code and replace any instance of the term you want to replace with the property name within @ symbols. Take the following PHP file.

<?php
/**
 *
 * This is a comment
 *
 *
 **/
$property1 = '@myProperty@';
echo 'Hello World!';
 
// another comment.

To replace the myProperty property with the value of "test", you need to use the replacetokens element, which can contain one or more token elements. The following build.xml file will replace all instances of the key myProperty with the value "test".

<?xml version="1.0"?>
<!-- build xml -->
 <project name="myProject" default="main">
 <property name="myProperty" value="test" />
 
 <fileset dir="./" id="myProjectFiles">
  <include name="**/*.php" />
  <exclude name="myProject_build/**" />
 </fileset>
 
 <target name="main">
  <copy todir="./myProject_build">
   <fileset refid="myProjectFiles" />
   <filterchain>
    <replacetokens>
      <token key="myProperty" value="${myProperty}" />
    </replacetokens>
   </filterchain>
   </copy>
 </target>
</project>

You will now see in your build output something like the following:

[filter:ReplaceTokens] Replaced "@myProperty@" with "test"

The token in each of the files will now be changed with the value of the property.

To see a list of the core filters available, take a look at the Phing filter appendix on the Phing website. You can even do something odd like only include the first 3 lines from each file, and append each line with the word "wibble".

<filterchain>
 <headfilter lines="3" />
 <prefixlines prefix="wibble: " />
</filterchain>

I can see why the headfilter might be useful in some instances where you want to test that your build file adds the correct file to each folder/zip file without including the whole thing. But where would you ever need to append a string to every line?

One final thing, if you change anything within your build file that replaces values then remember that phing will save time by not copying across any file that has already been copied and that hasn’t changed. This means that if you change a filter and update you will see no changes unless you do one or both of the following:

  • Manually delete any files in the target directories.
  • Add an overwrite attribute to the copy element(s) in your target element(s). This will force phing to simply overwrite the files every time, even if they haven’t changed.