-
Notifications
You must be signed in to change notification settings - Fork 2
Router
Pair\Core\Router parses the request URL and resolves:
- module
- action
- path params
- query params
- special tokens (
order-*,page-*,noLog)
It also supports custom routes from routes.php.
Default route structure:
/module/action/param1/param2/...
Example:
/persons/edit/42
- module:
persons - action:
edit - first param (
Router::get(0)):42
Controller mapping example:
class PersonsController extends Pair\Core\Controller {
// Reads the first path param after /persons/edit/.
public function editAction(): void
{
$id = Pair\Core\Router::get(0);
// Load the requested record.
// ...
}
}use Pair\Core\Router;
$router = Router::getInstance();
// Module/action resolved from the current URL.
$module = $router->module;
$action = $router->action;
// First SEF param after /module/action.
$id = Router::get(0);
// Query-string params are exposed with string keys.
$status = Router::get('status'); // from query stringRouter::get() and $router->getParam() are equivalent accessors.
You can also read through magic properties:
$module = Router::getInstance()->module;
$action = Router::getInstance()->action;If URL is:
/persons/list?status=active&year=2026
Router stores:
-
status=>active -
year=>2026
So you can read:
$status = Router::get('status');
$year = Router::get('year');After /module/action, Router recognizes:
-
order-N-> sets ordering value ($router->order) -
page-N-> sets current page ($router->getPage()) -
noLog-> disables AJAX log output ($router->sendLog() === false)
Example:
/persons/list/order-2/page-3/noLog
getPage() persists current page in cookie (scoped by module+action) and defaults to 1.
This is one of the most important Router behaviors in real modules:
-
setPage()stores the page in a cookie for 30 days -
resetPage()clears the persisted page and restarts from1 -
setOrder()resets pagination when the sort order changes - if the order has just changed,
setPage()ignores stalepage-*values carried by older URLs
You can reset it:
// Forces the next list render to restart from page 1.
Router::getInstance()->resetPage();Fallback helper when current page becomes invalid after data changes:
// Typical after deleting the last row of the current page.
Router::exceedingPaginationFallback();use Pair\Core\Router;
$router = Router::getInstance();
// Current state from the request or from the persisted cookie.
$currentOrder = $router->order ?? 1;
$currentPage = $router->getPage();
// A new order URL automatically drops the current page.
$sortByDateUrl = $router->getOrderUrl(2);
// A page URL keeps the current filters and order.
$nextPageUrl = $router->getPageUrl($currentPage + 1);$router = Router::getInstance();
// Builds the current route as-is.
$url = $router->getUrl();
// Rebuilds the same URL with another order or page value.
$orderUrl = $router->getOrderUrl(2);
$pageUrl = $router->getPageUrl(4);getUrl() includes:
- module/action
- indexed params
/order-*/page-*- query-string params
Detailed example:
$router = Router::getInstance();
// Adds a positional path param.
$router->setParam(0, '42');
// Adds a query-string param.
$router->setParam('status', 'active');
// Stores order/page in the generated URL.
$router->setOrder(2);
$router->setPage(3);
echo $router->getUrl();
// persons/edit/42/order-2/page-3?status=activeBuilds the canonical relative URL from the current router state already loaded in memory.
Use it when you have modified params with setParam(), setOrder() or setPage() and need one final redirect or link.
$router = \Pair\Core\Router::getInstance();
// Keeps the current route and adds one filter.
$router->setParam('status', 'archived');
// Useful in POST/redirect/GET flows.
$redirectUrl = $router->getUrl();Returns a copy of the current URL with another order value. When the order really changes, the generated URL drops the current page so the next request starts from the beginning of the list.
$router = \Pair\Core\Router::getInstance();
// Current URL: orders/list/page-4?status=paid
$orderUrl = $router->getOrderUrl(2);
// Result: orders/list/order-2?status=paidReturns a copy of the current URL with another page value, keeping route params, filters and order.
$router = \Pair\Core\Router::getInstance();
// Current URL: orders/list/order-2?status=paid
$pageUrl = $router->getPageUrl(3);
// Result: orders/list/order-2/page-3?status=paidStores either a positional path param (0, 1, 2, ...) or a named query-string param (status, year, ...).
When $encode = true, the value is compressed and made URL-safe.
$router = \Pair\Core\Router::getInstance();
// Stores a filter state token without unsafe URL characters.
$router->setParam('state', 'filters:status=paid;year=2026', true);
// Later you can decode the same param.
$state = \Pair\Core\Router::get('state', true);Pair loads custom routes from:
APPLICATION_PATH/routes.phpmodules/<module>/routes.php
Register routes with:
use Pair\Core\Router;
Router::addRoute('/modifyPerson', 'edit');Root shortcut with explicit module:
Router::addRoute('/login', 'login', 'user');With named placeholders:
Router::addRoute('/article/:slug', 'show');With regex placeholders:
Router::addRoute('/invoice/:id([0-9]+)', 'detail');When placeholders are matched, Router stores values into named vars (slug, id) so Router::get('id') works.
Example:
// URL: /invoice/1001
$invoiceId = Router::get('id'); // "1001"- custom routes are checked before standard parsing
- module-level routes are prefixed with module path automatically
- URL prefixes
raw/andajax/are ignored in path matching
Examples that can match the same custom rule:
/persons/get/4/ajax/persons/get/4/raw/persons/get/4
You can set fallback module/action when URL is empty:
Router::getInstance()->setDefaults('home', 'default');Get fallback URL:
$defaultUrl = Router::getInstance()->getDefaultUrl(); // "home/default"Router can store encoded values via setParam(..., true) and decode with get(..., true):
$router = Router::getInstance();
// Encodes a value so it can travel safely in the URL.
$router->setParam('stateToken', 'filters:year=2026;status=active', true);
// Decodes the same value when reading it back.
$stateToken = Router::get('stateToken', true);See also: Controller, View, Application, index.php.
These methods are used less often in day-to-day module code, but they matter when you customize routing behavior or bootstrap logic:
-
setDefaults(string $module, string $action): voidDefines the fallback route used for an empty URL. -
setModule(string $moduleName): voidAssigns the current module and definesMODULE_PATHif needed. -
setAction(?string $action): voidUseful when advanced bootstrap logic changes the destination action. -
resetParams(): voidClears current route params before rebuilding a URL programmatically. -
sendLog(): boolReturnsfalsewhen the request contains thenoLogtoken. -
routePathMatchesUrl(string $path, string $url): boolInternal matcher that also treatsajax/andraw/prefixes as transparent.
Read route context:
Router::get(int|string $paramIdx, bool $decode = false): ?stringgetParam(int|string $paramIdx, bool $decode = false): ?stringgetAction(): ?stringgetPage(): intsendLog(): bool
Write/update route context:
setModule(string $moduleName): voidsetAction(?string $action): voidsetParam(mixed $paramIdx, string $value, bool $encode = false): voidsetOrder(int $order): voidsetPage(int $number): voidresetParams(): voidresetPage(): void
Route config and URLs:
addRoute(string $path, string $action, ?string $module = null, ?bool $raw = false)setDefaults(string $module, string $action): voidgetDefaultUrl(): stringgetUrl(): stringgetOrderUrl(?int $val = null): stringgetPageUrl(?int $page = null): string
$router = \Pair\Core\Router::getInstance();
// /orders/list/order-2/page-3?status=paid
$status = \Pair\Core\Router::get('status') ?? 'all';
$order = $router->order ?? 0;
$page = $router->getPage();
// Builds a URL for "next page, same filters/order".
$nextPageUrl = $router->getPageUrl($page + 1);routes.php:
\Pair\Core\Router::addRoute('/invoice/:id([0-9]+)', 'detail', 'billing');Controller:
public function detailAction(): void
{
// Reads the named placeholder exposed by the router.
$invoiceId = (int)\Pair\Core\Router::get('id');
// Load the requested invoice and continue with the action.
}