PHP
downloads | documentation | faq | getting help | mailing lists | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

IIS> <Функции для работы с сервером Apache
Last updated: Fri, 28 Nov 2008

view this page in

virtual

(PHP 4, PHP 5)

virtualВыполнить подзапрос Apache

Описание

bool virtual ( string $filename )

Функция virtual() специфична для сервера Apache и является эквивалентом конструкции <!--#include virtual...-->, используемой в mod_include. Эта функция выполняет подзапрос Apache. Она бывает полезной в тех случаях, когда вам нужно включить в свой скрипт результат выполнения других CGI программ или скриптов, обработки сервером Apache .shtml файлов или чего-либо иного, что должно быть обработано Apache. Имейте в виду, что CGI скрипты должны создавать корректные CGI заголовки. Как минимум, CGI скрипт должен создавать заголовок Content-type.

Перед тем, как осуществится выполнение подзапроса, все буферы сбрасываются и выдаются в броузер, также отсылаются заголовки, помещенные в буфер.

This function is only supported when PHP is installed as an Apache module.

Список параметров

filename

Имя файла, для которого будет выполнен подзапрос.

Возвращаемые значения

Результат выполнения подзапроса в случае успеха, или FALSE при неудаче.

Список изменений

Версия Описание
4.0.6 Эту функцию стало возможным использовать для файлов PHP. Тем не менее, чаще всего для файлов PHP лучше использовать функции include() или require().

Примечания

Внимание

Строка запроса может быть передана вызываемому файлу, однако значение переменной $_GET будет скопирована из родительского скрипта. Лишь $_SERVER['QUERY_STRING'] будет содержать переданную строку запроса. Строка запроса может быть передана только при использовании Apache 2. Запрошенный файл не будет отражен в журнале доступа (access log) Apache.

Замечание: Переменные окружения, установленные в запрошенном файле, не видимы из вызвавшего его скрипта.

Замечание: Начиная с PHP 4.3.3 вы также можете использовать эти функции с модулем NSAPI в серверах Netscape/iPlanet/SunONE.



add a note add a note User Contributed Notes
virtual
Anonymous at spam dot org
08-May-2007 05:13
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.

This was with PHP 4.4.7 (released May 2007).
vcaron at bearstech dot com
07-Jul-2006 03:26
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 com
plex access pattern than mod_access allows you to do (say a MySQL lookup with your app logic), try this simple Apache rule:

  Order Allow,Deny
  Allow from env=PHP_ALLOW

Then in your PHP script, before sending any content or header:

<?php
$image
= "/some/URL/path/test.png";
if (
client_may_view_image($image)) {
 
apache_setenv('PHP_ALLOW', '1');
  if (
virtual($image))
    exit(
0);
  echo
"Ops, failed to fetched granted image $image (hammer your webmaster).\n";
} else
  echo
"Sorry buddy, you're not allowed in here.\n";
?>

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.
ruibal_DELETED_p*AT*gmail__dot__com
05-Feb-2006 03:04
when php is installed as an apache module, this works pretty well for writing your own php preprocessor/information logger. For example, requests to any URI underneath pre.php will first be executed by pre.php, then returned to the user.
<?
$docroot        = $_SERVER['DOCUMENT_ROOT'];
$script_root    = str_replace( basename($_SERVER['SCRIPT_NAME']),'',$_SERVER['SCRIPT_NAME'] );
$script_ext     = substr( $_SERVER['SCRIPT_NAME'], strrpos( $_SERVER['SCRIPT_NAME'],'.' ) );
$fakework_root  = $script_root.basename( $_SERVER['SCRIPT_NAME'] ).'/';
$framework_root = $script_root.'_'.basename( $_SERVER['SCRIPT_NAME'], $script_ext ).'/';
$frequest_root  = dirname( $framework_root.substr( $_SERVER['PATH_INFO'], 1 )).'/';
$frequest_name  = basename( $_SERVER['PATH_INFO'] );
$frequest_ext   = (strrpos($frequest_name,'.')===FALSE ? FALSE : strtolower(substr( $frequest_name, ( strrpos( $frequest_name, '.' )+1 ) ) ) );
$frequest_full  = $frequest_root.$frequest_name;
$doc_frequest   = $docroot.$frequest_full;
$doc_framework   = $docroot.$framework_root;

$DO_PARSE = in_array( $frequest_ext, $chk_exts );
if( $DO_PARSE )
{
    $tmpfname = tempnam( $doc_framework.'tmp', 'aj_' ).($frequest_ext? ('.'.$frequest_ext) : '');
    if( ($to_parse=@file_get_contents($doc_frequest))===FALSE )
        $to_parse="404";
    $tmpvname = str_replace( $docroot, '', $tmpfname );
    $tmpvname = str_replace( '\\\\', '/', $tmpvname );
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
//  Do processing of data stored in $to_parse
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
    $to_parse = striptags( $to_parse );

// - - - - - - - - - - - - - - - - - - - - - - - - - - -
    $handle = fopen($tmpfname, "w");
    fwrite($handle, $to_parse);
    fclose($handle);
    @virtual( $tmpvname.$getvars );
    unlink( $tmpfname );
}
else
    @virtual( $frequest_full.$getvars );

?>

So all files in http://server/sub/pre.php/path/ are really located in http://server/sub/_pre/path/

All this needs is some kind of caching mechanism.

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.
abentley at panoramicfeedback dot com
17-Jun-2003 10:29
Here's an update to tomwk's code:
function safe_virtual( $filename )
{
   $curDir = getcwd();
   virtual ( $filename );
   chdir( $curDir );
}

This is better if you've already changed your current directory to be something other than your script's directory.  It works for PHP4 and above.
php at n-wise dot com
02-Jan-2003 11:15
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;

foreach ($HTTP_POST_VARS as $header=> $value ){
 if($QSTRING==""){
    $QSTRING = $header.'='.urlencode($value);
 }else{
    $QSTRING = $QSTRING.'&'.$header.'='.urlencode($value);
 }
}
 
putenv('REQUEST_METHOD=POST');
putenv('CONTENT_TYPE=application/x-www-form-urlencoded');
putenv('CONTENT_LENGTH='.strlen($QSTRING));
putenv('QUERY_STRING='.$QSTRING);
unset($return_array);
exec('echo "'.$QSTRING.'"| '.$CGISCRIPT, $return_array, $return_val);

//The 1st line of my script was "Content...." ... so remove it!
$firstline=array_shift($return_array);
//evaluate the code
eval('?>'.implode($return_array,''));

?>
chardin at ssc dot wisc dot edu
07-Nov-2002 03:00
If you are having problems using virtual include becuase of files being stored in different directories, a root-relative path will make things much easier:

virtual ("/root directory/directory/filename.htm/");

where root directory is the root directory of your site (ask your sys admin if you dont know what it is) Don't include the protocol or host name.

This will also allow you to move your files around your site without having to redirect your includes which is *very* helpfull
crazyted at crazyted dot com
10-Jan-2002 11:57
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.

Hope this helps some ppl out:

  $cwd = getcwd();
  $script_name = "cgi-bin/perl_script.pl";
  $count = substr_count($cwd, '/');
  $count = $count - 3;
  // get rid of extra absolute paths since my directory is /home/user/www

  // Add additional path information
  for($i = 1; $i <= $count; $i++){
    $script_name = "../".$script_name;     
  }
  virtual($script_name);
s dot dan at free dot fr
31-Jul-2001 08:43
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:

// preparing the arguments passed to this PHP page
$QSTRING = $QUERY_STRING;

// pay attention to the maximum length of the QUERY string.
while (list ($header, $value) = each ($HTTP_POST_VARS)){
  if (empty($QSTRING))
    $QSTRING = $header.'='.$value;
 else
    $QSTRING = $QSTRING.'&'.$header.'='.$value;
}

putenv('REQUEST_METHOD=GET');
putenv('QUERY_STRING='.$QSTRING);

unset($return_array);
exec('my_CGI', $return_array, $return_val);

Now you can parse the output of 'my_CGI' in return_array.
logang at deltatee dot com
26-Apr-2001 07:21
If you want to pass all post and get values to the cgi script you can use this code:

<?php
$QSTRING
= $QUERY_STRING;
while (list (
$header, $value) = each ($HTTP_POST_VARS))
{
  
$QSTRING = $QSTRING.'&'.$header.'='.$value;
}

virtual($script.'?'.$QSTRING);
?>

It takes all the values of $HTTP_POST_VARS and appends them in the proper format to the values you get in $QUERY_STRING
david at audiogalaxy dot com
28-Nov-1999 10:44
Virtual returns the HTTP entity header after the requested file, when it's the first output to the page.

The work-around to prevent seeing the header is, of course, to output something (such as echo " "; ) before calling virtual.

 
show source | credits | stats | sitemap | contact | advertising | mirror sites