Skip to content

Assemblies

Greg Bowler edited this page Apr 14, 2026 · 1 revision

An Assembly is an ordered list of file paths.

Routing uses two assemblies:

  • the logic assembly
  • the view assembly

The router builds them up; another part of the application can then execute or render them in order.

Why assemblies exist

Many routed responses are made of more than one file. In WebEngine, for example, a request may include:

  • a shared _header.html
  • a page-specific index.html
  • a shared _footer.html
  • one or more logic files such as _common.php and a page-specific PHP file

The assembly gives us a single object that represents that ordered list.

Working with an assembly

Assembly implements Iterator and Countable, so we can append files and then loop over them later.

use GT\Routing\Assembly;

$assembly = new Assembly();
$assembly->add("page/_header.html");
$assembly->add("page/index.html");
$assembly->add("page/_footer.html");

foreach($assembly as $path) {
	echo $path, PHP_EOL;
}

The class also supports:

  • replace($oldPath, $newPath)
  • remove($path)
  • count()

Distinct files and magic files

Assembly::containsDistinctFile() answers a specific question: does the assembly contain anything more specific than the framework's magic wrapper files?

The magic filenames recognised here are:

  • _common
  • _header
  • _footer

If an assembly contains only those wrapper files, containsDistinctFile() returns false. This is useful when deciding whether a route has a page-specific match or only inherited shared files.

Adding files from a router callback

BaseRouter exposes protected helpers for adding to the current router's assemblies:

use GT\Routing\BaseRouter;
use GT\Routing\Method\Get;

class AppRouter extends BaseRouter {
	#[Get(path: "/")]
	public function home():void {
		$this->addToLogicAssembly("page/index.php");
		$this->addToViewAssembly("page/index.html");
	}
}

View class support

BaseRouter also allows a view class name to be set separately with setViewClass() and read with getViewClass(). That gives the wider application one more hook when it decides how to dispatch the matched route.

Access timing

getLogicAssembly() is only available after route() has completed. If we try to read it before routing, NotYetRoutedException is thrown.

getViewAssembly() can be read directly because view selection may begin while the router is still building up the route.


Assemblies often contain files found through content-aware matching. The next part of the routing decision is covered in content negotiation.

Clone this wiki locally