Dynamic routes
A route connects a URL to a controller. Hubleto does not have a routes file. Each app registers its routes in Loader::init(), so adding an app adds its URLs and removing the app removes them.
crud(): the routes of a model
$router->crud() registers the list/detail route and the add route of a model with a single call:
framework: src/Services/Router.php (excerpt)
public function crud(string $urlSlug, string $controllerClass): void
{
$urlSlugSanitized = str_replace('/', '\/', $urlSlug);
$this->get([
'/^' . $urlSlugSanitized . '(\/(?<recordId>\d+))?\/?$/' => $controllerClass,
'/^' . $urlSlugSanitized . '\/add\/?$/' => ['controller' => $controllerClass, 'vars' => ['recordId' => -1]],
]);
}
$this->router()->crud('price-lists', Controllers\PriceLists::class);
$this->router()->crud('price-lists/items', Controllers\Items::class);
get(): a single route
The first parameter is a regular expression (without the leading /), the second the controller:
apps/Invoices/Loader.php (excerpt)
'/^invoices\/api\/get-customer-info\/?$/' => Controllers\Api\GetCustomerInfo::class,
'/^invoices\/api\/get-supplier-info\/?$/' => Controllers\Api\GetSupplierInfo::class,
'/^invoices\/api\/create-invoice-from-prepared-item\/?$/' => Controllers\Api\CreateInvoiceFromPreparedItem::class,
'/^invoices\/api\/link-prepared-item\/?$/' => Controllers\Api\LinkPreparedItem::class,
'/^invoices\/api\/unlink-prepared-item\/?$/' => Controllers\Api\UnlinkPreparedItem::class,
'/^invoices\/api\/generate-invoice-number\/?$/' => Controllers\Api\GenerateInvoiceNumber::class,
'/^invoices\/api\/send-invoice-in-email\/?$/' => Controllers\Api\SendInvoiceInEmail::class,
- Start the expression with
^and end it with$. - Escape slashes:
\/. - Start with the slug of your app, so routes of apps never collide.
Variables in a route
A named group (?<name>...) becomes a variable that you read like a URL parameter:
// route
'/^invoices\/(?<idInvoice>\d+)\/?$/' => Controllers\Invoice::class,
// in the controller
$idInvoice = $this->router()->urlParamAsInteger('idInvoice');
Which route wins?
The router tests all registered routes in the order of registration and does not stop at the first match, so the last matching route wins. Two consequences:
- An overly general expression registered later swallows the specific ones registered earlier. Anchor the expressions.
- An app that is initialized later (or a project) can override a route of another app by registering the same URL. Use it deliberately.
Debugging routes
php hubleto debug router is meant to print the routes, but it is broken at the moment (see Other routes). Print them from a temporary controller:
var_dump(array_keys($this->router()->getRoutes(\Hubleto\Framework\Services\Router::HTTP_GET)));
