I develop a number of MODX Extras, both open source and bespoke code, which I typically build on the latest stable release. Using a build script the code is transformed into a transport package, which by default ends up in "core/packages" of the MODX installation. This short how-to will explain you how to adjust your build script and project setup and stay in control of your packages.

My Localhost

Now, before I go into detail on how to make this ridiculously easy change, I want to briefly discuss my project set up as that is of course a vital part of staying in control of your data. I've found this works for me, but of course different developers will have different strategies.

All my files are accessible via http://localhost/, ie they are in the "www" folder of WAMP. In there I have a number of MODX installations of various versions. These are for development & testing of stuff I develop and act as a source of documentation as well. On the same level (so immediately under "root") I have a folder called "projects". So to recap, we've got this:

  • www
    • modx-1.0.5
    • modx-2.0.8
    • <...>
    • modx-2.1.3
    • modx-git
    • projects

This allows me to keep my MODX installs totally separate from my project files. Using system settings I then "link" my project into the MODX install I'm developing that project in, and we're set (possible a more extensive blog post on that later!). If I break a MODX install or otherwise screw up, I can simply delete all the files of that install and start over.

In my projects directory I have one directory per project, which in 99% of the cases is also a Git Repository (Like VersionX2, or HandyMan). In there I have a _build, core and assets directory with the right contents - I assume you're familiar with that if you're reading this article.

The Problem..

When I develop a lot of addons, or make a lot of builds, all these are added to the core/packages directory of the MODX install I linked my package to (through a config.core.php file). May be fine if you then want to install the package there, but I don't to keep my links pointing to my own files. And after some time it gets tough to find that one package in between one of the other 100's..

What I want is store packages in a _packages dir in my project Git repository so I instantly know where a package should be (in the projects dir) and as an added bonus the package is also uploaded to Git - giving an easy way to distribute it for people that do not know how / don't want to run the build but do want to check out development.

Aha! The Solution!

In a random moment where I was again browsing into the MODX install dir to get a package, I decided to check out the modPackageBuilder class API docs.

As often is the case, this problem had already been foreseen and there is a very easy way to change the directory the files and transport zip are outputted to. It's so easy, it would have fit in a tweet - but how much fun would that be? So that's why you''ve been reading this blog.

Oh you want to know how now you got this far?

Okay.

Let's say this is part of our regular build script:

That's where it instantiates the modPackageBuilder class. So that's where we'll want to tell it where to output to. We'll be using a public property of the modPackageBuilder for that: $directory. Hah, bet you didn't see that coming!

So let's just make that single small adjustment to our build script that you've been reading this for..

We're simple traversing up two directories (first we're in _build, then we go up to the root, and lastly add _packages to it, putting it in our all new special directory :)

Now hold on.. what about all those files?

Yes - the package builder also creates a lot of files (that's what gets zipped up, actually) and we probably don't feel the need to upload all that to our git repository. To fix that, we'll create a real simple .gitignore file and put that in our _packages directory.

It will ignore all folders, but not files in the root (our transport package).

And that's it folks. :) Thanks for the masterminds Shaun & Jason for thinking of stuff like this ahead of time!

There is something, well, maybe not magical, but certainly productive about using xPDO queries within MODX as opposed to using plain SQL. I've created a really simple snippet which fetches children of a resource (if any) and outputs them in an unordered list. And this took no more than a few minutes to pull off.

Before getting started

You may be wondering what xPDO is. If you've not wrote custom code in MODX Revolution yourself yet, I can imagine the term might not sound familiar. xPDO stands for "open eXtensions to PDO" and it has been developed by part of the MODX Core Development team to provide an Object Oriented Programming approach to relational databases built upon PDO - a core function of PHP > 5.1. At the same time, it also provides (although slightly limited) support for PHP versions under that.

Anyway - that's not what I wanted to explain in this article. This article is about how you can use xPDO within MODX to easily create custom snippets which are very easy to read, fast to execute and can be customized at will without spending years learning a special language - it's all PHP.

getChildren

I designed this snippet cause I needed a simple way to output an unordered list of children of the current resource, but where using an existing addon (like getResources or Wayfinder) would feel like overkill. Of course they both have their own advantages compared to using this custom approach, but I'm being given the power to use this by MODX, it's probably faster (I didn't test it - but just have a look at the lines of code getResources uses and what my snippet uses) and I wont be touching it often after developing it anyway.

This is the actual snippet I'm using:

It's commented line by line, and those familiar with PHP will see what it does in an instant. There's a few things I'd like to point out in this case though:

  1. The script starts off with calling the $modx->resource->getMany('Children') method. What this does is tell MODX to use the current resource, and find associated children based on that resource.
  2. On line 6 shows the modX::getOption (inherited from xPDO:getOption) method, which is considered best practice to get settings and properties from in MODX Revolution. It accepts three parameters:
    1. (string) name of the option (setting, property) you want to retrieve. In this case I'm looking for the tpl parameter.
    2. (options array) variable name you want to get it from. Within snippets you'll use $scriptProperties.
    3. (string) default value if there's no value found for the option name. In this case I set it to an empty string.
  3. When it starts going through each of the children found, it first sets an array with the different resource fields I want to have available in my template chunk, and get the value using the ->get('fieldname') method. When it has all the data in the $out array, it will take those fields and use $modx->getChunk($chunkname,$placeholders) to populate the template with the placeholders, and in turn add that output to the $o variable.
  4. Lastly, it finishes the outer markup and returns the output to the snippet call.
Now let's look at the tpl chunk.

The chunk is really straight forward. It creates a list item element, adds in an anchor (hyperlink) tag and uses the placeholders that are set. It also uses the link tag syntax to create a link and the "default" output filter, which sets the value of the placeholder to what's included in the `` quotes if the placeholder value is empty. So in this case, that acts as a backup in case I didn't set a menu or a longtitle (assuming there will always be a pagetitle).

What remains now is showing you how to call it (assuming you named your Snippet getChildren, and your chunk getChildrenTpl):

Conclusion

Don't be hesistant to coding your own snippets - xPDO and the MODX api makes the most common tasks ridiculously easy. This snippet took a couple of minutes to make and by spending a couple more minutes you could improve it easily to also use an outer template instead of mixing PHP and HTML... but it suited my needs as it is :)

What do you think about using custom coding in your development?