I recently ran into a CGI/web programming puzzle involving PHP that I thought I'd comment on, with dueling objectives: 1) to spare someone else the confusion, and possibly 2) to see if any one else has come up with a better solution. The issue is this:

We start with a standard CGI scenario involving a form whose action launches an A-Shell session that uses CGIUTL (CGIOP_MRGOUT) to merge some data with a template HTML file to create the new page output. So far so good. The problem starts when a block of PHP code is added to the template file, so that the template file looks something like this...
Code
Content-type: text/html
Status: 200 OK

<html>
<head>
<title> Sample Response Page With PHP Inserts </title>
</head>
<body>
...
<?php
    <php code here>
?>
</body></html>

With the PHP code inserted, the CGI operation still works, but it doesn't actually process the PHP code; it just comes out like plain text.

Why? Because the web server (at least in the case of Apache), expects plain text/html (per the Content-type header) to be coming back from the CGI interface. So it doesn't invoke the PHP module. Note that when you browse to a file with a .php extension (or otherwise configure the web server to treat other extensions like php), it invokes the php module to pre-process the file, converting it to html before sending the result to the browser. The browser itself does not understand PHP. So we need for the CGI process to handle the PHP processing itself before passing the new page output back to the server via the stdout channel.

Workaround #1: The ideal solution would simply be to get the web server to pass the output from the CGI process back through the PHP module, just like it does when it is instructed to load a .php file from disk. It seems like that should be possible via the Content-type header, but I was unable to find something that worked. (Content-type: text/php doesn't work.)

Workaround #2: Some reading of the Apache documentation suggests that one might be able to use mod_filter to filter the CGI result back through the PHP processor. If that works, it would be ideal, since it would require no further modification to the CGI code. But I wasn't quite sure how to set that up, and in any case it wouldn't work with another web server.

Workaround #3: Invoke the PHP processor explicitly from within the CGI program in order to create plain HTML text that can then be passed back to the web server as normal CGI output. This worked, and only required a couple of changes to the CGI code, from this...
Code
! merge variables with template and send back to web server via stdout...
xcall CGIUTL,CGIOP_MRGOUT, template$, status, varsub1, varsub2, ...

to this:
Code
! merge variables with template to create a temporary php file...
open #ch, temp'php$, output
xcall CGIUTL,CGIOP_MRGFIL,template$, status, ch, varsub1, varsub2, ...
close #ch

! invoke the php processor, sending output to another temp file
xcall HOSTEX, "cmd.exe /c php -f " + temp'php$ + " > " + temp'html$

! send the output from the php process back to the web server via stdout...
xcall CGIUTL,CGIOP_MRGOUT, template$, status

kill temp'php$   ! clean up
kill temp'html$  ! clean up

Notes:
  • Make sure that your temp files are uniquely named, perhaps including the pid, so that multiple instances don't step on each other!
  • Keep in mind that the template$ in this case isn't a fully formed PHP program file; it's just a HTML file with the CGI content header and blocks of PHP code inserted via the <?php ... ?> wrapper.
  • The HOSTEX call above assumes Windows; for UNIX you would drop the cmd.exe /c and possibly the redirection and subsequent CGIOP_MRGOUT call, letting the php processor send its stdout directly.


Although this solution would require updating every one of your CGI programs in order to support PHP, hopefully all of them use a common function to perform the above steps, in which case it would just be a matter of recompiling them all.

While tinkering with this approach, you may find it useful to test your php command from the dot prompt, which you can do with the HOST.LIT command, something like this...
Code
    .host cmd.exe /c php -f test.php > test.lst
    .eztyp test.lst

That would quickly reveal whether you have php installed and in the path. (Maybe you need to specify the full path to php.exe.) This would also allow you to make sure that the end result (test.lst in this example) has the proper CGI header followed by a valid HTML document. (The web server isn't likely to be very friendly about malformed output, spitting out something unhelpful like "Internal error".)