PHP Code Interpolation¶
10/19/26: Mod. by D
PHP Test Code¶
The following code snippet is a simple test to verify whether PHP code interpolation is working correctly, in which case the current date and time will be displayed below the code snippet.
<?php
// Set the default timezone
date_default_timezone_set( 'America/Los_Angeles' );
echo 'Page last updated: ' . date( 'F d, Y, h:i:s a.', filemtime( __FILE__ ) );
echo '<br>Path: ' . __FILE__;
echo '<br>' . date( 'l, F j, Y, ' ) . date( 'h:i:s a' );
?>
Path: /opt/zensical/zensical-project/site/php-test.html
Sunday, November 15, 2026, 10:07:39 am
Is the current date and time shown immediately above? Reload to change it.
PHP Configuration¶
Loaded Configuration File: /etc/php-zts/php.ini
Setting up PHP interpolation¶
Our Zensical subdomains are served by FrankenPHP, which adds fast PHP code interpolation to its underlying Caddy web server. Zensical runs its own web server on a separate localhost port but it is not suitable for production service. As a backend server it can be safely reverse-proxied to the internet via FrankenPHP:
### Begin zen-proxy.langley.stream configuration ###
zen-proxy.langley.stream {
# Reverse proxy the Zensical server running on localhost port 8006:
reverse_proxy localhost:8006
}
### End zen-proxy.langley.stream configuration ###
Unfortunately FrankenPHP offers no easy way to execute any PHP code flowing from a reverse-proxied backend server,
it needs to directly access the static HTML files built by Zensical, located in the project’s site directory.
But what if we can’t serve files directly from the location of our Zensical installation,
for instance if it’s running in root’s home directory? We can copy Zensical’s static site
directory into the standard web root at /var/www or /opt/<project-name> (Debian-based Linux):
Note
If the destination folder already exists and you want to copy the contents of the source directory directly into it without nesting folders, append /. to the source path.
When FrankenPHP is configured to serve static Zensical files directly, without reverse proxy,
it can interpolate embedded PHP code, provided that it has been configured to treat files with the
.html extension as though they were .php files:
### Begin zen-php.langley.stream configuration ###
zen-php.langley.stream {
root /opt/zensical/zensical-project/site
@phpFiles {
path *.html *.php
}
php @phpFiles
encode
php_server
}
### End zen-php.langley.stream configuration ###
Adjust directory structure¶
Normally Zensical builds navigation using directory-based links, without specifying index.html files. The use_directory_urls setting in zensical.tomlcontrols the directory structure of your documentation site,
and thereby the URL format used for linking to pages. Turn it off to generate file-based URLs, facilitate offline
usage, and enable interpolation of PHP code embedded in .html files.
Note that this is automatically set to false when building for offline usage,
so your documentation can be browsed from a local filesystem without a web server. The default value is true.
Add modification date to footer¶
Add the page modification date in the footer’s copyright notice:
[project]
copyright = """Copyright © 2026 Dennis C. Langley <br> \
<?php \
date_default_timezone_set( 'America/Los_Angeles' ); \
echo 'Mod. ' . date( 'm/d/Y, h:i:s a.', filemtime( __FILE__ ) ); \
?>"""
Auto-load PHP scripts¶
First create a new directory in our project’s docs directory named phpscripts.
It will hold all our project’s php scripts.
A single common php code file named common.php, will be included at the
head of every page.
Per-page php code files named <page-name>.php will be included on each
matching page. For example, if a page markdown file is named front.md, the php file
docs/phpscripts/front.php will autoload into the header of
the corresponding html page, front.html, after the front.md page is built by
Zensical and then served by FrankenPHP.
Here’s where the magic happens. By extending Zensical’s “base.html” template, we can
insert a php code snippet into the extrahead block of each page which will
include the matching php files if they exist:
{% extends "base.html" %}
{% block extrahead %}
<!-- This is my custom extrahead block. -->
<?php
$file = $_SERVER['DOCUMENT_ROOT'] . '/phpscripts/common.php';
if ( file_exists( $file ) ) include $file;
$file = pathinfo( __FILE__, PATHINFO_FILENAME ) . '.php';
if ( file_exists( $file ) ) include $file;
?>
{% endblock %}