Docs Stemplates Version 1.x Relative Includes

Relative Includes

When a template file moves into a subfolder, PHP relative paths break. Here's the one-time fix.

This is the most common issue encountered when moving templates into subfolders. It is a one-time fix and once done it doesn't matter where a template lives.

The Problem

PHP resolves relative include and require paths from the location of the current file. When a template moves from a flat structure to a subdirectory, those paths break:

// template was at: /site/templates/blog-post.php
// include worked fine:
include("includes/get-widget.inc");
// template moves to: /site/templates/blog/blog-post.php
// PHP now looks for: /site/templates/blog/includes/get-widget.inc
// — that file doesn't exist, so it fails.

This affects include, require, include_once, and require_once — any statement that uses a path relative to the current file.

The Fix

Replace every relative path with an absolute path using ProcessWire's $config->paths->templates, which always points to /site/templates/ regardless of where the calling file lives:

// Before — breaks when the template is in a subdirectory
include("includes/get-widget.inc");
require("includes/functions.php");
// After — works from any depth, forever
include($config->paths->templates . "includes/get-widget.inc");
require($config->paths->templates . "includes/functions.php");

Finding All Occurrences

Run a search across your templates directory to find every instance that needs updating. In most editors or from the terminal:

grep -rn 'include\|require' site/templates/ | grep -v 'config->paths'

This lists every include/require that does not already use $config->paths. Work through the list and update each one.

What About __DIR__?

__DIR__ is another safe option — it resolves to the directory of the file it appears in. However, if you're including a shared file from templates at different depths, $config->paths->templates is cleaner because it gives you an absolute root anchor rather than a relative offset:

// __DIR__ works but requires knowing the depth
include(__DIR__ . "/../includes/get-widget.inc");  // from one level deep
include(__DIR__ . "/../../includes/get-widget.inc"); // from two levels deep — fragile
// $config->paths->templates is always the same regardless of depth
include($config->paths->templates . "includes/get-widget.inc");

Checklist

  • Search for include( and require( across all template files
  • Replace relative paths with $config->paths->templates . "path/to/file"
  • Check any shared _init.php or _func.php files — these often have their own includes
  • Check UIkit/chunk files if you use ProcessWire's template engine
  • Verify the site loads without errors after moving a template

Once updated, your includes will work correctly from any subfolder depth — both with Stemplates Free (naming convention) and Stemplates PRO (auto-discovery).