Utility classes

So-called utility classes are often considered an antipattern in object-oriented programming, but in some cases they may be just what the doctor ordered. This page contains instructions on adding a simple Utils class to a Wireframe site.

The /site/templates/lib/ directory is always a good place to stash code that doesn't really belong to any single Controller, view file, layout file, or partial. This directory and the namespace Wireframe\Lib are automatically added by the Wireframe module to the list of autoload directories managed by ProcessWire's WireClassLoader.

For the purpose of this example you should place the following code into /site/templates/lib/Utils.php:

<?php
  
namespace Wireframe\Lib;
  
/**
 * Utility class
 */
final class Utils {
  
    /**
     * This utility class should never be instantiated.
     */
    private function __construct() {}
  
    /**
     * Does something clever with provided Page and returns the resulting string.
     *
     * @param \ProcessWire\Page $page Source Page object.
     * @return string Resulting string.
     */
    public static function methodName(\ProcessWire\Page $page): string {
        return $page->name . " has " . $page->numChildren() . " children!";
    }
  
}

We've declared our Utils class as "final" because there shouldn't be any reason to ever extend this from other classes. (Obviously you can omit this part if extending makes sense in your use case.) Additionally we've made the constructor method private so that Utils cannot be instantiated; this is simply because it's meant to be used statically.

This class can be used for storing general purpose utility methods. Make sure that all your methods are static, and don't forget to add an applicable "use" statement to your code before calling methods from Utils:

<?php namespace ProcessWire;
  
use Wireframe\Lib\Utils;
  
echo Utils::methodName();

While it's likely very rare, it should be noted that since we're working in the ProcessWire namespace, there may be clashes between ProcessWire classes and our own, site-specific classes. If your class happens to have the same name as an existing ProcessWire class, you can get past this issue by utilizing aliasing:

<?php namespace ProcessWire;
  
use Wireframe\Lib\Utils as WireframeUtils;
  
echo WireframeUtils::methodName();

Alternatively, if you prefer to omit the use statement, you can add the namespace prefix to the class call manually:

<?php namespace ProcessWire;
  
echo \Wireframe\Lib\Utils::methodName();

Keep in mind that while it can be tempting to stash everything into a single Utils class, a giant utility class will make your code hard to maintain and likely difficult to grasp. If you have multiple related domain-specific methods, you should consider splitting them into separate classes instead. Some examples of these domain-specific utility classes might include RenderUtils, FormUtils, MailUtils, and ImportUtils.

Back to top