Virtual: примеры (PHP)
virtual(string filename): boolФункция virtual() в языке PHP выполняет подзапрос к веб-серверу, используя механизм CGI (Common Gateway Interface). Основное её назначение — выполнение скрипта на стороне сервера и отправка результата непосредственно в выходной поток браузера, аналогично тому, как если бы запрос был выполнен напрямую. Эта функция специфична для серверов, поддерживающих CGI (например, Apache с модулем mod_cgi или mod_cgid).
Использование virtual() может быть актуально для включения результатов работы других CGI-скриптов или статических файлов, обрабатываемых сервером (например, .shtml файлов с Server Side Includes).
Функция принимает один обязательный аргумент:
- $uri (string) — путь к файлу, который должен быть выполнен сервером. Путь должен быть относительным к корневому каталогу документов сервера и, как правило, не должен содержать элементы вроде "../" для выхода за его пределы, а также символы строки запроса или якоря.
Функция возвращает bool: TRUE в случае успешного выполнения подзапроса или FALSE при неудаче. Важно отметить, что успех означает, что сервер принял запрос, но не гарантирует корректность выполнения целевого скрипта.
Вывод целевого скрипта отправляется непосредственно клиенту и не может быть захвачен в переменную стандартными средствами PHP без использования буферизации вывода.
<?php
// Выполнение скрипта counter.cgi, который, например, показывает количество посещений
$result = virtual('/cgi-bin/counter.cgi');
if (!$result) {
echo "Не удалось выполнить подзапрос.";
}
?>(Вывод скрипта counter.cgi, например: "Посещений: 12345")
<?php
// Предполагается, что сервер настроен на обработку .shtml файлов с SSI
virtual('/includes/footer.shtml');
?>(Содержимое файла footer.shtml после обработки сервером, например, HTML с текущей датой)
<?php
if (!virtual('/non_existent_file.cgi')) {
echo "Функция virtual вернула false. Скрипт, вероятно, не найден или нет прав доступа.";
}
?>Функция virtual вернула false. Скрипт, вероятно, не найден или нет прав доступа.
Поскольку virtual() устарела и зависит от конфигурации сервера, чаще используются другие средства:
include,require— включают и выполняют код из указанного файла непосредственно в текущем контексте скрипта. В отличие отvirtual(), результат можно захватить и обработать.readfile()— выводит содержимое файла. Подходит для статических ресурсов, но не выполняет скрипты.file_get_contents()— получает содержимое файла или URL в строку, что позволяет гибко манипулировать данными.curlилиstream_context_create()— для выполнения HTTP-запросов к другим скриптам или API, включая те, что находятся на том же сервере, но с полным контролем над запросом и ответом.
Использование include или curl обычно предпочтительнее из-за переносимости и лучшего контроля над выполнением.
Прямого аналога virtual() нет. Для выполнения подзапросов к тому же серверу используются механизмы роутинга фреймворка или HTTP-клиенты.
import requests
# Выполнение GET-запроса к другому эндпоинту того же приложения
response = requests.get('http://localhost:5000/api/data')
print(response.text)В Node.js можно использовать встроенные модули для выполнения HTTP-запросов или дочерних процессов.
const http = require('http');
// Запрос к другому маршруту сервера
const options = { hostname: 'localhost', port: 3000, path: '/data' };
const req = http.request(options, (res) => {
res.on('data', (chunk) => { console.log(chunk.toString()); });
});
req.end();Virtual в MySQL
Прямой аналогии нет. SQL — язык запросов к базе данных, не предназначенный для выполнения серверных подзапросов.
<?php
// На сервере, где не настроен CGI (например, nginx без FastCGI)
virtual('/cgi-bin/test.cgi');
?>Предупреждение: virtual() has failed. Функция вернет FALSE.
<?php
// Путь за пределами корневой директории или к несуществующему файлу
virtual('/../etc/passwd'); // Может быть отклонено сервером
?>Функция, скорее всего, вернет FALSE, возможно предупреждение безопасности в логах.
<?php
$output = virtual('/script.cgi'); // $output будет TRUE/FALSE, а не выводом скрипта
echo $output;
?>1 // (true) Вывод script.cgi уже ушел в браузер, а здесь выводится 1.
- PHP 8.0.0: Функция
virtual()объявлена устаревшей. Её использование вызывает предупреждение типаE_DEPRECATED. Это связано с тем, что CGI-режим работы PHP и сами CGI-скрипты становятся менее распространенными, уступая место встроенным SAPI (Server API) и современным архитектурам. - В более ранних версиях (PHP 4, 5, 7) функция работала без изменений, но всегда зависела от поддержки со стороны веб-сервера.
- В будущих мажорных версиях PHP функция может быть полностью удалена.
<?php
ob_start(); // Включаем буферизацию
$success = virtual('/cgi-bin/generate_report.cgi');
$captured_output = ob_get_clean(); // Получаем содержимое буфера
if ($success) {
// Обрабатываем $captured_output, например, ищем данные
if (preg_match('/Total: (\d+)/', $captured_output, $matches)) {
echo "Найдено значение: " . $matches[1];
}
} else {
echo "Подзапрос не выполнен.";
}
?><?php
$page_component = '/components/header.shtml';
// Проверяем существование файла перед вызовом virtual
if (file_exists($_SERVER['DOCUMENT_ROOT'] . $page_component)) {
virtual($page_component);
} else {
virtual('/components/default_header.shtml');
}
?><?php
function logged_virtual($uri) {
error_log("Запуск virtual для: $uri", 3, "/var/log/myapp/virtual.log");
$result = @virtual($uri); // Подавляем возможные предупреждения
error_log("Результат: " . ($result ? 'OK' : 'FAIL'), 3, "/var/log/myapp/virtual.log");
return $result;
}
logged_virtual('/cgi-bin/legacy_tracker.cgi');
?>Скрипт, вызываемый через virtual(), может отправлять собственные HTTP-заголовки (например, Location для редиректа). Эти заголовки будут отправлены клиенту и могут повлиять на дальнейшее выполнение основного скрипта.
<?php
// main.php
virtual('/cgi-bin/redirect.cgi'); // Этот скрипт может отправить header('Location: /other.php');
// Этот код может не выполниться, если был отправлен редирект
echo 'Этот текст может не появиться.';
?>