Managing Paths in MODX Extras II

Retrieving the paths from the namespace object

In the last article we looked at a number of versions of the traditional method for managing paths in your development environment when creating a MODX extra. In this one, we'll look at a new way of doing it using the Namespace object.

MODX logo

The Problem (review)

This is just to refresh your memory. If your extra has one or more class files, you need to load them (often at more than one point in your extra). Since you're working on the extra, you want to load the development version of your class. That means you're not going to get it from the standard install location: assets/components/my_extra/. Instead, you'll be loading them from wherever your development code is — the same place you keep your build files. The same thing happens with other files you might want to modify or replace such as JavaScript, CSS, or image files.

The traditional solution, is to create a System Setting to hold the local development core path (and often the local development assets path), like this:

Setting Key: myExtra.core_path
Value: c:/xampp/extras/assets/mycomponents/my_extra/core/components/my_extra/

Setting Key: myExtra.assets_path
Value: c:/xampp/extras/assets/mycomponents/my_extra/assets/components/my_extra/

The settings are not included in the build stage of the project so you're the only one who will have them. In the code, if a setting exists, it gets used. If not, the code creates a path to the standard install location and uses that. This can take several forms. Here's a common one:

$extraCorePath = $modx->getOption('myExtra.core_path',null,
    MODX_CORE_PATH . 'components/orphans/');
include $extraCorePath . 'model/myclass.class.php';

A New Way

I realized recently that since all extra packages must have a namespace, and namespace objects in MODX have fields to store a core path and an assets path, there's no reason why these can't be used to specify paths in an extra. The trick is to set the "development" core and namespace paths manually in the namespace object but set the traditional ones in your built.transport.php file (MyComponent will do the second one automatically).

To set the development paths, go to System (gear icon) -> Namespaces. Right-click on the namespace of your extra and select "Update Namespace." Set the Core Path and Assets Path to match your development location, then click on the "Save" button. My development files are under assets/mycomponents/ so the settings look like this:

Core Path

Assets Path

The Build Code

In your build.transport.php file, add code to set the two standard paths near the top of the file right after calling createPackage(), like this:

$modx->loadClass('transport.modPackageBuilder', '', false, true);
$builder = new modPackageBuilder($modx);
$builder->createPackage(PKG_NAME_LOWER, PKG_VERSION, PKG_RELEASE);

/* Create namespace and set core and assets path */
$assetsPath = '{assets_path}components/' . PKG_NAME_LOWER . '/';
$corePath = '{core_path}components/' . PKG_NAME_LOWER . '/';
$builder->registerNamespace(PKG_NAME_LOWER, false, true, $corePath, $assetsPath);

Notice that we used the "placeholders" {assets_path} and {core_path}. This is a good practice because without them, things will crash if the directories are moved and/or renamed.

Retrieving the Paths

Now that you have the dev. paths set in the namespace and have set thing up so the standard production paths will be set for any users who install your extra, you can write some very easy-to-understand code that will always get the appropriate paths for you to use in include and require statements:

$namespace = 'myextra';

/* Get the namespace object */
$obj = $modx->getObject('modNamespace', array('name', $namespace));

/* Get the assets and core paths */
$componentCorePath = $obj->getCorePath();
$componentAssetsPath = $obj->getAssetsPath();

include $componentCorePath . 'model/myclass.class.php';

The code above will get the dev. paths in your local install, and the standard production paths for all users who install the extra. There are a couple of things to notice here.

First, the namespace object has no key field, so you always have to retrieve it using the name field, which is its primary key. Because we're getting it by its primary key, the object is small (just three fields), and all namespaces are cached, the retrieval will be very fast.

Second, to get the paths, we called the namespace object's getCorePath() and getAssetsPath() methods rather than using get() on the specific fields (path, and assets_path). This is important because get() will not translate placeholders like {core_path} and {assets_path} that are often used in namespace paths.

What About the Assets URL?

To include CSS and JavaScript files, you often need the assets URL. Since you will be working on the CSS and JS files, you want to use the dev. version of the assets URL in your local development environment. We'll discuss that in the next article.

Coming Up

In the next article, we'll look at what to do about the assets URL, which can't be stored in the namespace object.

Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)

Comments (0)

Please login to comment.