
Prepending PHP to a Page in Gatsby

It goes against the entire Jamstack philosophy to add reliance to a back‑end technology like PHP, and certainly the Gatsby Content Mesh advocates against it, but sometimes there's simply no alternative.
Often, these server‑side scripts can be set up as standalone endpoints which you can then call via HTTP (for example ‑ by using axios). This is a really common approach for one‑way communication, like submitting a contact form. In Gatsby, if you are confident that your eventual hosting environment supports PHP (for example) you can even add these files into your static folder, safe in the knowledge that they will then be placed in, and be available at, the root of your domain.
However, there are times when this isn't sufficient. A recent project I worked on required that every page load be hydrated with up‑to‑the‑minute live pricing data, acquired from a monolith system built in PHP, where security policies made it impossible to use a more familiar, distributed approach. You might argue: possibly not the best use of a static site generator!

So, the answer in this instance was to use a include ‑ prepended to each generated page at build‑time, to build an object on window, then read back into the React components on‑page.
Another good use example for me has been to append a tiny piece of PHP to my error page. This way, I can collect data about what errors are occurring on‑site, what type of visitors are causing them, and react accordingly. This also has a benefit against the more accepted HTTP‑client approach: it doesn't require a visitor with JavaScript enabled (which inevitably more nefarious bots do not).
From here, I'm going to assume you're serving your Gatsby site on a PHP environment with access to htaccess. Otherwise, this solution isn't going to work for you.
Use .htaccess to Allow PHP Processing
The html files generated by Gatsby are not ‑ on their own ‑ going to trigger any PHP you attempt to push into them without a little help.
If you don't already have an htaccess file in your project, create one (important: the file name is .htaccess ‑ there is nothing before the extension, your OS is probably going to hide it immediately). This goes into your static folder and will then be copied into your site root on build.
Then, there are two options in the code block below to use as best suits your needs:
- The first will mean that all files with the
.htmlextension should be parsed as PHP. I don't recommend this unless you really and genuinely are relying on the back‑end for every page (in which case, maybe Gatsby isn't the answer). - The second does the same but only applies to a specific file ‑ in this case
404.html.
AddType application/x-httpd-php .html<Files 404.html> AddType application/x-httpd-php .html</Files>Install prepend‑file
prepend‑file is a simple package which just prepends text to a file within your generated site. We will use this as part of our deployment script. So, add to your project by simply running yarn add prepend‑file from the project root (unless you're using NPM, in which case it's npm install prepend‑file).
Write Your Prepend Script
This is a very similar process as I've described before where we want to add additional Node.js functionality within our build process. Create a file called prepend.js in your folder root, import prepend‑file, and configure it to add an include to your PHP file to the file you want to add PHP to.
This is how I capture hits on my error page (with some comments to explain what's going on). Note that I'm also using my LIVE_DEPLOY environment variable here to determine where the build is occurring.
// import our environment variablesrequire('dotenv').config({ path: '.env' });// if our LIVE_DEPLOY variable isn't set, or is not set// to 'true', then we return without going any furtherif (process.env.LIVE_DEPLOY !== 'true') { console.warn('Deploy env is false, not prepending'); return;}// import prepend-filevar prependFile = require('prepend-file');// open the 404 file, and inject an include for// error-include.phpprependFile('./public/404.html', "<? include_once('include.php'); ?>", () => { console.log('Error file prepend successfully');});What this does is open the generated 404.html from the public folder and append a simple string of text:
<? include_once('include.php'); ?>
From here, as long as you've created a file called include.php, and put it inside your static folder, then its contents will be added into the base of your 404.html file. When the page is loaded by a visitor, whatever PHP you've written will also be triggered.
Add Prepend to Your Build Script
Much like setting up Gatsby to deploy via FTP, one final task is to add your new prepend script into your build process and much of this will come down to your own personal preference.
Inside my package.json, I like to have a specific 'deploy' script which is only called (via yarn deploy) within the pipeline I have configured to push content out onto the live site. Mine looks like this:
"scripts": { "deploy": "gatsby clean && gatsby build && node prepend && node deploy"}In order, this chains four commands together:
gatsby clean‑ make sure we have cleared out any cached items we don't need;gatsby build‑ build the Gatsby project;node prepend‑ calls our newprepend.jsfile which in turn adds a PHP include to our404.htmlfile;node deploy‑ callsdeploy.jswhich takes a copy of the contents of thepublicfolder, and uploads it via FTP. I've written about this here.
And it is as simple as that! If you wish to try this locally, you can simply run node prepend and then look at the source code of the file in your public folder (assuming you have a recent build in there already). Just be sure to set your LIVE_DEPLOY environment variable to true, otherwise, it will just say no.
Categories:
Related Articles

Automatically Generate urllist.txt from sitemap.xml. Automatically Generate

Adding Static Files to a Gatsby Site. Adding Static Files to a Gatsby Site

Understanding Event Loop and Concurrency in JavaScript. Understanding Event Loop and Concurrency in JavaScript

Block Bad Bots Using .htaccess. Block Bad Bots Using
.htaccess
LeetCode Container with Most Water: The Two‑Pointer Solution. LeetCode Container with Most Water: The Two‑Pointer Solution

Why Next.js Middleware Might Be Unavailable with Pages Router. Why Next.js Middleware Might Be Unavailable with Pages Router

Building Design Systems for Web Applications with Figma, Storybook, and npm. Building Design Systems for Web Applications with Figma, Storybook, and npm

Angular Standalone Components: Do We Still Need Modules? Angular Standalone Components: Do We Still Need Modules?

Detecting and Dealing with Website Theft. Detecting and Dealing with Website Theft

Object Property Shorthand and Computed Property Names in JavaScript. Object Property Shorthand and Computed Property Names in JavaScript

LeetCode: The 'Trapping Rain Water' Problem with Two‑Pointer Approach. LeetCode: The 'Trapping Rain Water' Problem with Two‑Pointer Approach

Prefix and Suffix Products: Solving 'Product of Array Except Self'. Prefix and Suffix Products: Solving 'Product of Array Except Self'