druvu-lib-web
Write your pages in PHP. Run them on the JVM. A small Java web framework on Jetty 12 whose templates are real PHP 8, executed by Java. No PHP runtime, no FPM, no mod_php.
One thing is deliberately different from PHP: output is HTML-escaped by default, and raw() is the opt-out. Forgetting is safe. Published to GitHub Packages, which needs a one-time token to read. See Install.
Try it
Write the page:
<!-- dashboard.php -->
<?php require 'includes/header.php'; ?>
<h1>Welcome, <?= $customer->name ?></h1>
<ul>
<?php foreach ($orders as $order): ?>
<li><?= $order->reference ?> — <?= number_format($order->total, 2) ?></li>
<?php endforeach; ?>
</ul>
Give it something to show:
public class DashboardHandler implements HttpHandler {
@Override
public void handle(HttpRequest request, HttpResponse response) {
request.setAttribute("customer", customer); // becomes $customer
request.setAttribute("orders", orders); // becomes $orders
}
}
Start the server:
WebBoot boot = new WebBoot(WebConfig.builder()
.port(8080)
.route(Route.forEveryone(DashboardHandler.class))
.authConfig(AuthConfig.builder()
.basicAuth()
.user("admin", "secret")
.build())
.build());
boot.start("/myapp");
// Server running at http://localhost:8080/myapp/dashboard
What you get
- Real PHP 8 in the templates. Variables, every control structure, string interpolation, heredocs, includes, arrow functions and 115 standard functions. Whole templates are matched against PHP’s own output, byte for byte.
- Routing by convention.
DashboardHandleranswers/dashboard. A handler that does not commit a response falls through to the matching template;response.commit("application/json", json)answers JSON instead. - Sign-in built in. Basic auth with inline users, OpenID Connect through one provider (no password is ever stored), bearer tokens for machines. Permissions per route, checked before the handler runs.
- WebSocket with JSON messages and session management.
- WebJars.
webjar('bootstrap.min.css')finds the file, with no version in the template. - Template engines are plugins, discovered via ServiceLoader. Drop a jar, it is picked up.
Install (GitHub Packages)
Java 25. GitHub Packages needs Maven authentication even for a public package. Once per machine: a token with the read:packages scope and a server entry in ~/.m2/settings.xml:
<servers>
<server>
<id>github</id>
<username>YOUR_GITHUB_USERNAME</username>
<password>YOUR_GITHUB_TOKEN</password>
</server>
</servers>
Then in the project, the repository, the core, and the PHP engine at runtime:
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/DenissLarka/druvu-lib-web</url>
</repository>
</repositories>
<dependency>
<groupId>com.druvu</groupId>
<artifactId>druvu-lib-web-core</artifactId>
<version>3.0.0</version>
</dependency>
<!-- PHP template engine (loaded automatically via ServiceLoader) -->
<dependency>
<groupId>com.druvu</groupId>
<artifactId>druvu-lib-web-php</artifactId>
<version>3.0.0</version>
<scope>runtime</scope>
</dependency>
The full reference, the PHP dialect, the handler and WebSocket contracts, is the README.
Something it almost does?
Open an issue, or write to me. If it is small and useful to more than you, I will often just build it.
Apache License 2.0.