virtual

(PHP 4, PHP 5)

virtual — Perform an Apache sub-request

Description

boolvirtual
( string$filename
)

virtual() is an Apache-specific function which
is similar to <!--#include virtual...--> in
mod_include.
It performs an Apache sub-request. It is useful for including
CGI scripts or .shtml files, or anything else that you would
parse through Apache. Note that for a CGI script, the script
must generate valid CGI headers. At the minimum that means it
must generate a Content-Type header.

To run the sub-request, all buffers are terminated and flushed to the
browser, pending headers are sent too.

This function is supported when PHP
is installed as an Apache module or by the NSAPI server module in Netscape/iPlanet/SunONE
webservers.

Parameters

filename

The file that the virtual command will be performed on.

Return Values

Performs the virtual command on success, or returns FALSE on failure.

Examples

Notes

Warning

The query string can be passed to the included file but
$_GET is copied from the parent script and only
$_SERVER['QUERY_STRING'] is filled with the passed
query string. The query string may only be passed when using Apache 2.
The requested file will not be listed in the Apache access log.

Note:

Environment variables set in the requested file are not visible to the
calling script.

Note:

This function may be used on PHP files. However, it is typically better
to use include or require for
PHP files.

See Also

User Contributed Notes 13 notes

Problem with most of the scripts posted below is that virtual() flushes the pending headers before making the subrequest. Requesting an image with virtual() still returns a text/html type document.A workaround is to set the content-type first. But that requires getting the content-type first.

I'm using the following script for now. A disadvantage is that Apache makes 2 subrequests.

I have a header that's include()'ed on each of my pages. I then wanted to add a Perl script to that header file (header.php) via the virtual() command.

Since my header is used by documents in my /www folder along with other folders inside that (and inside those), and virtual() seems to take only relative paths, I had to write some code to dynamically get the path to the perl script.

This documentation is not clear enough. Parameter $filename is not a filename as on the filesystem, but a URI. It can be absolute, starting with /, or relative to URI that involved the PHP script which called virtual(). (I.e. if the PHP script that calls virtual() is invoked via PHP require/require_once/include/include_once mechanism and it passes a relative URI to virtual(), then that URI must be relative to the URI of the topmost PHP script on the inclusion stack.)

Not sure how relative URIs work if the request which calls virtual() was processed through Apache rewrite rules.

While the virtual() function has it's promising sides, there exists issues when using it in relation to a cache system such as eAccellerator. The issue becomes that the first time you load with a virtual file, it will seem to work fine. But once the cache is put into play, the virtual call will end up returning nothing at all, and basically returning a blank page.

Please realize that this is not an issue with virtual(), but instead an issue of the cacheing application. Should anyone else have a similar issue, hopefully this will shed some light onto this subject.

Note that QUERY_STRING seems to get inherited, so to make a virtual request WITHOUT one, one needs to explicitly append a "?" to the URL of the sub-request (to cause the creation of a "null" query string). Of course, if the desired URL has its own query string, that will override and an additional "?" should not be appended.

You can use virtual() to implement your own dispatcher/auth handler in an efficient and effective way.

For instance if you have a bunch of images you would like to be served statically by Apache (its job after all), but with a more complex access pattern than mod_access allows you to do (say a MySQL lookup with your app logic), try this simple Apache rule:

Of course very Apache-ish, but it's much more efficient and uniform to rely on Apache rather than passthru() and mime_content_type() hacks : it does the path lookup and auth/security audit as the admin expects, use the best static serving it can (think 'sendfile') and you can even chain your request with another embedded script eg. in mod_perl.

But yeah, this could be modified to add watermarks with the image functions, convert to xml with Tidy, check for extensions better with mimeTypes, proxy content with cURL, validate $_SERVER['HTTP_REFERER'] or $_SERVER['HTTP_USER_AGENT'], etc etc

This gives you much more over than the auto_prepend_file, and auto_append_file, for certain functionality

The key is the virtual function _because_ it delivers the modified content with an apache subrequest.

I saw the note above about the length of the query string... but didn't know what it was, so have altered the code so it can post to the script.Probly only works on nix systems as it makes use of the echo function...This code also will look evaluate the result, so you can get cgi to dynamically create PHP (probly best to watch out that posted variables do not include script!)<?$CGISCRIPT="./cgi-bin/cgiscript.cgi"; // preparing the arguments passed to this PHP page $QSTRING = $QUERY_STRING;

Another way of passing arguments:
If you have some CGI programs that depend on some libraries where you can't change the source code (in my case an online payment library), you can pass the arguments by changing some environment variables.

Of course the CGI program has to get the GET/POST variables in the usual manner.
It simulates, more or less, a direct call from the server to a CGI program: