Routes and redirects
Routes created from the manager, stored in pb_routes. For everything a content editor needs to do without touching a file: move a page, retire an old address, point a URL at a template.
PageBlocks → Routes.
A row
| Field | What it is |
|---|---|
context | MODX context the route belongs to |
method | HTTP method, GET by default |
uri | The address, without a leading slash |
type | What happens — see below |
target | Where it goes: a URL, a template, a chunk or a controller action |
status | HTTP status for redirects. 301 by default |
menuindex | Order, which decides who wins among equals |
published_at | An unpublished route does not exist |
Types
| Type | target is | What happens |
|---|---|---|
redirect | A URL | Redirect to it with status |
redirect_controller | Controller@method | The action's URL is resolved from the registered routes, then redirected to |
controller | Controller@method | The action handles the request |
view | A MODX template | Renders that template |
file_chunk | A Fenom file under core/App/elements/ | Renders that file |
redirect_controller exists so a redirect survives a change of address: you point at the action, and the URL is looked up at runtime. If the action cannot be resolved, the row is skipped rather than redirecting somewhere wrong.
301 by default, on purpose
A redirect entered by hand almost always means "this address has moved for good". 302 tells search engines the opposite and keeps the old URL in the index. Set 302 only when the move really is temporary.
Who wins
Routes come from two places — files and this table — so the order is fixed:
- Redirects win over everything for the same
GETURI. A file route for that address is skipped, whether the redirect came from a file or from the table. - Among redirects, the first one wins; duplicates for the same URI are dropped rather than crashing the dispatcher.
- For
controller,viewandfile_chunk, file routes win. The table only fills addresses no file has claimed.
The third rule is what makes the table safe to hand to an editor: a row cannot quietly take over an address your code already serves.
A redirect does override your code
The first rule is the exception, and it is deliberate — retiring an address has to work even when something still answers there. If a working page suddenly redirects, look in this table before the routes directory.
Caching
The rows are read once and cached; the model clears that cache when a route is saved or deleted, so a change takes effect immediately.
A failed read — the table not migrated yet, the database briefly unavailable — is not cached. Otherwise a single bad moment during a deploy would freeze an empty route list until the next cache clear.
When to use a file instead
The table is for addresses. Anything with logic — conditions, parameters, access checks — belongs in core/App/routes/, where you can read it in a diff and test it. See Routing.