Is it possible to use Hugo template functions and variables in a PHP file?


I have a PHP contact form, which currently resides in /static/contact.php file. Keeping it up to date with changes that I commit to my theme is very inconvenient, because whenever I modify something in layouts, I need to manually propagate the change to contact.php. And usually I miss a thing or two.

contact.php loads two external .html files (with include statement), which are located outside of my Apache public path:

  • contact-form.html stores layout of the contact form,
  • message-status.html bases on $GET from contact.php to display appropriate message about mail delivery status (sent or failed)

/contact/ URL is redirected to /contact.php via RewriteRule, so there’s no markdown involved at all.

Is it somehow possible to take advantage of Hugo’s template functions and variables in PHP files? Ideally, I’d like the contact form to use my layouts/_default/baseof.html — load head.html, header.html and footer.html partials and execute contact.php as main block.

I tried putting a test PHP file in /assets, but when Hugo is building the website, it seems to be ignoring any PHP files from that path.

You have 2 options (at least):

  1. Put your php file in /assets and use resources.ExecuteAsTemplate to … execute it as a template.
  2. Create a new custom output format for PHP and create layouts as normal.

I think you would want 2). Note that I suspect that you would need to duplicate your templates to “index.php”/“baseof.php” etc., but I guess you can solve that duplication mostly with partials.

1 Like

Thanks, I think I’ll explore the suggested second route.

As I understand it, it would be best to provide a MimeType in place of * in [mediaTypes.*] (config.toml) in a new media type definition. Do you have any suggestions on the choice of MimeType for PHP files? It is not on the list of IANA media types. Would application/x-php, suggested here be OK? I don’t think it would cause any “disadvantages”, like those described in this article. I suspect that whatever I were to type there, will not have any impact on Hugo. Am I correct?

That PHP MIME type would be just for internal/your use – so it can be anything.

I’ve read Custom Output Formats a couple of times and I’m confused. Here’s what I’ve done so far:

I created mediaTypes and outputFormats in config.toml

        suffixes = ["php"]

        baseName = "index"
        isPlainText = false
        mediaType = "text/x-php"

I created /content/contact/index.php file. For simplicity’s sake, it contains only phpinfo() nested in main block, but let’s pretend that there are actual contact form routines, plus some PHP includes: :slightly_smiling_face:

{{ define "main" }}
{{ end }}

In /layouts/contact I created baseof.php:

<!DOCTYPE html>
    {{- partial "head.html" . -}}
        {{- partial "header.html" . -}}
        <div id="content">
            {{- block "main" . }}{{- end }}
        {{- partial "footer.html" . -}}

And a simple index.php:

{{ define "main" }}
    {{ .Content }}
{{ end }}

The phpinfo() executes properly in /contact/, but Hugo’s magical incantations fail, so at the beginning and the end of the /contact/ page I’m greeted with {{ define "main" }} and {{ end }}. Neither the head, header nor footer are loaded.

To be honest, the existence of /layouts/contact/baseof.php and /layouts/contact/index.php doesn’t seem to affect /contact/index.php in any way. It executes fine with or without them.

What am I doing wrong?

Okay, it turned out that the shared hosting service which I use, isn’t too friendly to PHPMailer (and in general — to sending mail via postmaster directly from PHP). No matter how hard I tried, I couldn’t push even a single message out of the server. It probably would send it, if I were to configure the script as you would your everyday MUA, but I didn’t want to leave my SMTP password sitting in a text/plain format on a shared user space on a server completely beyond my control. Perhaps it’s time to move to a VPS and be the king of my own castle (at least to some degree)?

Anyway, if anyone in the future wants to hijack this thread, feel free to do so. There are only a few things worse in the World than forum threads without a solution. :wink: