Routing
File-based routing and pattern-based routing are available. Pattern-based routes can execute callables or target files. Some variables are exposed to these routes, and others can be added manually. .php
files have special features, and other files are delivered as-is. The Server addon compiles requests and processes routes.
Hooks can be added to certain stages of routing, such as to add Markdown Support, or to choose a single route when there are multiple matches for a URL.
Static public files can be delivered via a static method without loading up Liaison.
See the Theme documentation for delivering HTML responses as JSON.
Related: Theme/Page Layout, Markdown Support, Hooks, Packages, Router Addon, FastFileRouter, Route Object, Response Object,Request Object , Server
Docs
- File based routing (
/public/
dir) - Static public files
- Pattern-based routing & callable routes
- Variables exposed to public files
- Multiple Routes / Resolving conflicts
- Expose variables to public files
- Remove/Replace Routes
File based routing
Place files in the /public/
directory of your Package to make them automatically deliverable, or add a directory manually. By default, public files are only deliverable via GET requests.
URL of files:
- Every URL is prefixed with your package's base url. Your Site package usually will have a base url of
/
- non-php files will be delivered at their respective path with appropriate headers. Ex:
public/reedybear.jpeg
delivers at/reedybear.jpeg
-
.php
files are delivered without their extension. Ex:public/my-cats.php
is available at url/my-cats/
-
index.php
is removed from the path. Ex:public/index.php
is the root path for your package at/
.public/my-dogs/index.php
is delivered at/my-dogs/
. - Files can contain variable path components. Ex: file
public/bears/{bearname}.php
will deliver at/bears/reedy/
,/bears/samantha/
, and others.$bearname
will be exposed to{bearname}.php
POST Requests:
- Prefix a file name with
@POST.
to support POST requests. Ex:public/@POST.submit-bear.php
(This disables GET requests) - For POST & GET together, use
@POST.@GET.
. Ex:public/@POST.@GET.bear-request.php
. This could be a file that displays a form for GET requests and handles submission of the form for POST requests.
Add a directory:
All files within the target directory will be added with the same rules as above. Though, with this method you can hide other file extensions, not just .php
.
<?php
\Lia\Addon\Router::from($package->lia)
->addDirectoryRoutes(
$package, // \Lia\Package instance or null
$package->dir('/admin-routes/'), // directory, absolute path
$package->url('/admin/'), // base_url for the routes
['.php'], // array of extensions to remove
);
Static public files
Deliver static public files quickly, without loading up Liaison, using the FastFileRouter. Can also execute PHP files.
Put this at the top of your deliver script: (You can even require FastFileRouter.php directly to skip autoloading.
<?php
// deliver php files. Requested URL must end with a trailing slash. No browser caching.
\Lia\FastFileRouter::php(__DIR__.'/fastroute/',$args=[]);
// deliver non-php files. Uses browser caching.
\Lia\FastFileRouter::file(__DIR__.'/file/');
// Send a file manually. Uses browser caching.
\Lia\FastFileRouter::send_file(__DIR__.'/path-to-file.css');
Note: php()
and file()
prevent path traversal by removing all occurences of ..
.
Pattern-based routing & callable routes
Routes can be manually added by providing a pattern and a target file or callable.
<?php
// pattern to file
\Lia\Addon\Router::from($lia)
->addRoute(
'/pattern/',
__DIR__ .'/target-file.php',
$package // \Lia\Package instance or null
);
// pattern to callable, with variable
\Lia\Addon\Router::from($lia)
->addRoute(
'/bears/{bearname}/',
function(\Lia\Obj\Route $route, \Lia\Obj\Response $response){
$bearname = $route->param('bearname'); // or $route->var(0)
$response->content = \My\Custom\Script::get_bear_page_for($bearname);
}
$package // \Lia\Package instance or null
);
Variables exposed to public files
<?php
/**
* Several variables are always passed to a public file.
*
* - Any variable portions of a pattern (Ex: `/blog/{slug}/` exposes `$slug`)
* - If `$slug` is already defined in the current scope, then it will be `$routeslug` instead
* - $package->public_file_params are `extract`ed and available to your public file.
*
* @var Lia\Obj\Route $route The requested route
* @var Lia\Obj\Response $response The response (*you can modify the headers*)
* @var Lia $lia
* @var Lia\Package $package The package your this route belongs to.
*/
echo 'hi i\'m tired';
Multiple Routes / Resolving conflicts
The FILTER_ROUTE
hook can be used to remove routes from the route list when multiple routes have matched a request.
<?php
// example routes. We want to choose the static routes over the dynamic routes for this example.
$router->addRoute('/bear/sasha/', $dir.'/sasha-bear.php');
$router->addRoute('/bear/jimbo/', $dir.'/jimbo-bear.php');
$router->addRoute('/bear/{bearname}/', $dir.'/dynamic-bear.php');
\Lia\Addon\Hook::from($lia)
->add(\Lia\Hooks::FILTER_ROUTE,
function (\Lia\Obj\Route $route, array $routeList): bool {
if (count($routeList)==1)return true; // there is only one route, allow it
else if ($route->paramaterizedPattern() == '/bear/{bearname}/'){
// this removes the dynamic route and allows the static routes
return false;
}
// always return true by default
return true;
}
);
Expose variables to public files
Public files have access to the \Lia\Package $package
instance they belong to. If you subclass Packages
, just add properties or getter methods to your subclass, so that your public file can access them via $package->property
or $package->getProperty()
.
If you are not subclassing Package
, then use Package::$public_file_params
, a key=>value
array of paramaters to expose to your public files.
Example:
bootstrap.php
:
<?php
/**
* This file is loaded after the base Package class is initialized, before addons are loaded. For access to addons within your package, call `$this->load_addons()`. For guarantees that other packages are loaded, setup hooks here (*assuming you've loaded the main package first*).
*
* @param $this \Lia\Package the package this bootstrap file belongs to (typically a subclass)
*/
$pdo = new \PDO(...);
$this->public_file_params['pdo'] = $pdo;
public/index.php
:
<?php
$stmt = $pdo->prepare("SELECT * from bear_names");
$stmt->execute();
$bear_names = $stmt->fetchAll();
// print bear names as you please
Remove/Replace Routes
Routes can be removed via \Lia\Addon\Router::from($lia)->removeRoute('/pattern/')
, using the same pattern rules that are used for adding routes. You can then addRoute(...)
to a file or callable of your choice.
Tip: Use the \Lia\Hooks::REQUEST_STARTED
hook to replace routes, as all packages are initialized and routes are setup by this point. See Hooks
<?php
$router = \Lia\Addon\Router::from($lia);
// added by another package, perhaps
$router->addRoute('/bears/', __DIR__.'/bad-route-target.php');
// remove the bad route
$router->removeRoute('/bears/');
// add your own route
$router->addRoute('/bears/', __DIR__.'/my-better-version.php');
Note: If multiple routes have been added for the same pattern, removeRoute()
will remove all of them.