Customizing Build
It is possible to customize the Propel build process by overriding values in your propel build.properties
file. For maximum flexibility, you can even create your own Phing build.xml
file.
Customizing the build.properties
The easiest way to customize your Propel build is to simply specify build properties in your project's build.properties
file.
Understanding Phing build properties
Properties are essentially variables. These variables can be specified on the commandline or in properties files.
For example, here's how a property might be specified on the commandline:
> phing -Dpropertyname=value
More typically, properties are stored in files and loaded by Phing. For those not familiar with Java properties files, these files look like PHP INI files; the main difference is that values in properties files can be references to other properties (a feature that will probably exist in in INI files in PHP 5.1).
Importantly
properties, once loaded, are not overridden by properties with the same name unless explicitly told to do so. In the Propel build process, the order of precedence for property values is as follows:
- Commandline properties
- Project
build.properties
- Top-level
build.properties
- Top-level
default.properties
This means, for example, that values specified in the project's build.properties
files will override those in the top-level build.properties
and default.properties
files.
Changing values
To get an idea of what you can modify in Propel, simply look through the build.properties
and default.properties
files.
Note, however, that some of the current values exist for legacy reasons and will be cleaned up in Propel 1.1.
New build output directories
This can easily be customized on a project-by-project basis. For example, here is a build.properties
file for the _bookstore _project that puts the generated classes in /var/www/bookstore/classes
and puts the generated SQL in /var/www/bookstore/db/sql
:
propel.project = bookstore
propel.database = sqlite
propel.database.url = sqlite://localhost/./test/bookstore.db
propel.targetPackage = bookstore
# directories
propel.output.dir = /var/www/bookstore
propel.php.dir = ${propel.output.dir}/classes
propel.phpconf.dir = ${propel.output.dir}/conf
propel.sql.dir = ${propel.output.dir}/db/sql
The targetPackage property is also used in determining the path of the generated classes. In the example above, the Book.php
class will be located at /var/www/bookstore/classes/bookstore/Book.php
. You can change this bookstore
subdir by altering the targetPackage property:
propel.targetPackage = propelom
Now the class will be located at /var/www/bookstore/classes/propelom/Book.php
Note that you can override the targetPackage property by specifying a package="" attribute in the <database>
tag or even the <table>
tag of the schema.xml.
Creating a custom build.xml file
If you want to make more major changes to the way the build script works, you can setup your own Phing build script. This actually is not a very scary task, and once you've managed to create a Phing build script, you'll probably want to create build targets for other aspects of your project (e.g. running batch unit tests is now supported in Phing 2.1-CVS).
To start with, I suggest taking a look at the build-propel.xml
script (the build.xml script is just a wrapper script). Note, however, that the build-propel.xml
script does a lot and has a lot of complexity that is designed to make it easy to configure using properties (so, don't be scared).
Without going into too much detail about how Phing works, the important thing is that Phing build scripts XML and they are grouped into targets which are kinda like functions. The actual work of the scripts is performed by tasks, which are PHP5 classes that extend the base Phing Task class and implement its abstract methods. Propel provides some Phing tasks that work with templates to create the object model.
Step 1: register the needed tasks
The Propel tasks must be registered so that Phing can find them. This is done using the <taskdef>
tag. You can see this near the top of the build-propel.xml
file.
For example, here is how we register the <propel-om>
task, which is the task that creates the PHP classes for your object model:
<taskdef
name="propel-om"
classname="propel.phing.PropelOMTask"/>
Simple enough. Phing will now associate the <propel-om>
tag with the PropelOMTask class, which it expects to find at propel/phing/PropelOMTask.php
(on your include_path). If Propel generator classes are not on your include_path, you can specify that path in your <taskdef>
tag:
<taskdef
name="propel-om"
classname="propel.phing.PropelOMTask"
classpath="/path/to/propel-generator/classes"/>
Or, for maximum re-usability, you can create a <path>
object, and then reference it (this is the way build-propel.xml
does it):
<path id="propelclasses">
<pathelement dir="/path/to/propel-generator/classes"/>
</path>
<taskdef
name="propel-om"
classname="propel.phing.PropelOMTask"
classpathRef="propelclasses"/>
Step 2: invoking the new task
Now that the <propel-om>
task has been registered with Phing, it can be invoked in your build file.
<propel-om
outputDirectory="/var/www/bookstore/classes"
targetDatabase="mysql"
targetPackage="bookstore"
templatePath="/path/to/propel-generator/templates"
targetPlatform="php5">
<schemafileset dir="/var/www/bookstore/db/model" includes="*schema.xml"/>
</propel-om>
In the example above, it's worth pointing out that the <propel-om>
task can actually transform multiple schema.xml
files, which is why there is a <schemafileset>
sub-element. Phing filesets are beyond the scope of this HOWTO, but hopefully the above example is obvious enough.
Step 3: putting it together into a build.xml file
Now that we've seen the essential elements of our custom build file, it's time to look at how to assemble them into a working whole:
<?xml version="1.0">
<project name="propel" default="om">
<!-- set properties we use later -->
<property name="propelgen.home" value="/path/to/propel-generator"/>
<property name="out.dir" value="/var/www/bookstore"/>
<!-- register task -->
<path id="propelclasses">
<pathelement dir="${propelgen.home}/classes"/>
</path>
<taskdef
name="propel-om"
classname="propel.phing.PropelOMTask"
classpathRef="propelclasses"/>
<!-- this [default] target performs the work -->
<target name="om" description="build propel om">
<propel-om
outputDirectory="${out.dir}/classes"
targetDatabase="mysql"
targetPackage="bookstore"
templatePath="${propelgen.home}/templates"
targetPlatform="php5">
<schemafileset dir="${out.dir}/db/model" includes="*schema.xml"/>
</propel-om>
</target>
</project>
If that build script was named build.xml
then it could be executed by simply running phing in the directory where it is located:
> phing om
Actually, specifying the om target is not necessary since it is the default.
Refer to the build-propel.xml
file for examples of how to use the other Propel Phing tasks -- e.g. <propel-sql>
for generating the DDL SQL, <propel-sql-exec>
for inserting the SQL, etc.
Found a typo ? Something is wrong in this documentation ? Just fork and edit it !