(Semi-)automatic MODx migrations using Phing

MODx is a very popular PHP/MySQL content management system – no surprise when you look at its flexibility, light weight and ease of use. However, as any MODx developer will attest, it is not without its quirks.

One of those problems is the lack of (automated) support for maintaining separate development and staging or production environments, and migrations between those environments. MODx saves content, templates and code snippets in its database, without versioning. Even though the Revolution branch (MODx has recently launched the first release candidate) aims to solve this by introducing the Transport Package concept, many developers will still need to support installations that run on MODx Evolution.

The code featured in this blog post is a mix of a Phing task that is executed on the development machine, and a small script that is uploaded to the staging or production machine. The task uses the MODx manager log to detect the changes made since a particular date. It then tries to match those changes to the database on the staging/production machines, and collates the changes to a SQL file.

In my case, I usually can’t access a production database from my development machine – this is where the updserver script comes in. It returns mysqldump-style output to the Phing task, and should be uploaded to your staging / production machine and installed in the same directory MODx resides in.

The syntax of the task call in the build file is as follows:

<?xml version="1.0"?>
<project name="MODx update" default="update">
        <target name="update">
            <taskdef name="modxchanged" classname="ModxChangedTask"/>
            <modxchanged
                hostname="localhost" username="root"
                password="test123" database="modx123"
                remoteurl="http://localhost/modx/" remotekey="test123"
                prefix="" timestamp="${timestamp}"/>
        </target>
</project>

In this example, MODx is installed on localhost/modx/. The remote key is the same as the remote database password.

Running the task should result in an SQL file that can be executed on the staging/production machine, and output similar to the following:

MODx update > update:
Searching changes from 1970-01-01:
===== Templates =======================================
NONE
===== Documents =======================================
[ 10] Test                          2010-03-24 19:58:41 [NEW]
===== Chunks ==========================================
NONE
===== Snippets ========================================
NONE
BUILD FINISHED

The code in this post is very much a work-in-progress, so there are a few caveats / unimplemented features:

  • Does not correctly handle conflicting/shared id’s
  • Does not process deleted items
  • Checking (and manually adjusting) the generated SQL file is always a good idea

Any comments or questions are highly appreciated! You can also e-mail me directly at info AT touchdownconsulting.nl!

DOWNLOAD (modx-migration-286.tgz)

Using Different Loggers In Phing

“When you run a phing script it will print things out to the console. These messages are either system messages (eg. BUILD STARTED) or echo messages that you have put into your build.xml file. All of this output is controlled and created by a logger file. The default logger is called (unsuprsingly) DefaultLogger and will be used as a default. There are a few different types of logger available, all of which can be found in the listener folder in your PEAR\phing directory.”

READ MORE