Frontends based on xp-forge/web
.
Frontend uses handler classes with methods annotated with HTTP verbs to handle routing. These methods return a context, which is passed along with the template name to the template engine.
use web\frontend\{Handler, Get, Param};
#[Handler]
class Home {
#[Get]
public function get(
#[Param('name')]
$param
) {
return ['name' => $param ?: 'World'];
}
}
For the above class, the template engine will receive home as template name and the returned map as context. The implementation below uses the xp-forge/handlebars library to transform the templates.
use com\handlebarsjs\{HandlebarsEngine, FilesIn};
use io\Path;
use web\frontend\Templates;
class TemplateEngine implements Templates {
private $backing;
public function __construct(Path $templates) {
$this->backing= (new HandlebarsEngine())->withTemplates(new FilesIn($templates));
}
public function write($name, $context, $out) {
$this->backing->write($this->backing->load($name), $context, $out);
}
}
The handlebars template is quite straight-forward:
Finally, wiring it together is done in the application class, as follows:
use web\Application;
use web\frontend\{AssetsFrom, Frontend, Templates};
class Site extends Application {
/** @return [:var] */
public function routes() {
$assets= new AssetsFrom($this->environment->path('src/main/webapp'));
$templates= new TemplateEngine($this->environment->path('src/main/handlebars'));
return [
'/favicon.ico' => $assets,
'/static' => $assets,
'/' => new Frontend(new Home(), $templates)
];
}
}
To run it, use xp -supervise web Site
, which will serve the site at http://localhost:8080/. Find and clone the example code here.
In real-life situations, you will not want to put all of your code into the Home
class. In order to separate code out into various classes, place all handler classes inside a dedicated package:
@FileSystemCL<./src/main/php>
package de.thekid.example.handlers {
public class de.thekid.example.handlers.Home
public class de.thekid.example.handlers.User
public class de.thekid.example.handlers.Group
}
Then use the delegation API provided by the HandlersIn
class:
use web\frontend\{Frontend, HandlersIn};
// ...inside the routes() method, as seen above:
new Frontend(new HandlersIn('de.thekid.example.handlers'), $templates);
When using the production servers, the application's code is only compiled and its setup only runs once. This gives us lightning-fast response times: