Managing Paths in MODX Extras III

What to do about the assets URL

In the last article we looked at a new way of using local development assets and core paths in your extra by retrieving them from the namespace object. In this one, we'll look how to use a local dev. assets URL.

MODX logo

The Problem

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, but not in the production environment for users who install your extra. There's no room for the assets URL in the namespace object, so we can't use the method described in the previous article.

The Solution

This is best done using a System Setting: myExta.assets_url, as described in the first article of this series. Set the System Setting to your local dev. assets url, then use code like this in your extra:

$componentAssetsUrl = $modx->getOption('myExtra.assets_url',
    null, MODX_ASSETS_URL . 'components/my-extra/';
include $componentAssetsUrl('js/myextra.js');

At one point, I developed a method for calculating the assets URL from the assets path retrieved from the namespace. I don't think it's practical to use, since the method above is much simpler and possibly more reliable, but you might find it interesting:

function normalize($path) {
    if (strpos($path, '\\') === false) {
    /* Nothing to do */
        return $path;
    } else {
        return str_replace('\\', '/', $path);

function getComponentAssetUrl ($namespace) {
    /* Get the Namespace Object */
    $obj = $modx->getObject('modNamespace',
        array('name' => $namespace));

    /* Get the namespaces's assets path */
    $nsAssetsPath = $obj->getAssetsPath();

    /* Use the MODX assets path if it's empty or not set */
    $nsAssetsPath = empty($nsAssetsPath)
        ? MODX_ASSETS_PATH . '/components/' . $namespace
        : $nsAssetsPath;

    /* Convert the assets path to the assets URL */
    $nsAssetsPath = str_replace($this->normalize(dirname(MODX_BASE_PATH)),
        '', $nsAssetsPath);

    /* Normalize and get the base of the assets URL */
    $base = $this->normalize(dirname(MODX_ASSETS_URL)) . '/';

    /* Remove the site URL from the normalized base */
    $short = str_replace($base, '', $this->normalize(MODX_SITE_URL));

    /* Add the assets path to the base */
    return $short . $nsAssetsPath;

$componentAssetsUrl = getComponentAssetsUrl('extra-namespace');
include $componentAssetsUrl . 'css/my-extra.css';

The comments explain how the method works, but the call to normalize() needs some explanation. Because we don't know what the directory separator is in the user's environment, the directory separators used in the namespace's assets path, the MODX_SITE_URL constant, and the MODX_ASSETS_URL, may not be the same. As a result, we can't use a simple str_replace() to remove the base. We first have to make sure all strings use the same directory separator.

It's possible to use the DIRECTORY_SEPARATOR constant for this, but it's simpler to just set all the separators to a slash (/). That's what the normalize() function does. It just replaces all backslashes with slashes in any string passed to it. By "normalizing" the strings, we can be sure they all have the same directory separators.

Coming Up

The next article will be my 300th blog post!.

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.