Создание настольных приложений на PHP: от PHP Desktop до альтернатив
Способы создания десктопных приложений на PHP
PHP Desktop
PHP Desktop (phpdesktop.com) - это обёртка, которая объединяет встроенный веб-сервер (PHP), браузерный движок WebKit (Chrome) и среду выполнения Windows (поддерживаются Linux и macOS через Wine или кросс-компиляцию). Приложение состоит из HTML, CSS, JavaScript для интерфейса и PHP для логики. Всё упаковывается в один исполняемый файл.
Цель: быстрое создание кроссплатформенного десктопного приложения с веб-интерфейсом, не требующее установки веб-сервера или браузера.
Установка: скачать архив с официального сайта и распаковать. В папке www размещаются PHP и HTML файлы. Файл settings.json задаёт конфигурацию.
Пример простого приложения
Создадим приложение, которое выводит «Привет, мир!» и версию PHP.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PHP Desktop App</title>
</head>
<body>
<h1>Привет из PHP Desktop</h1>
<?php
$version = phpversion();
echo "<p class='fw-bold'>Версия PHP: $version</p>";
?>
</body>
</html>обработка php (обработка данных в php)
Поместите этот файл в www/index.html. Запустите phpdesktop-chrome.exe (Windows) или соответствующий исполняемый файл для вашей ОС.
Проблема: файл не открывается, ошибка 404
Причина: неверный путь к файлу в URL. По умолчанию приложение открывает localhost:8080 и ищет index.html или index.php в корне www. Если файл называется иначе, его нужно указать в адресной строке: http://localhost:8080/другое_имя.html.
Решение:
изменить стартовую страницу в settings.json в разделе website -> startup_file.Проблема: PHP-код не выполняется, выводится как текст
Причина: файл с расширением .html, а PHP обрабатывает только .php.
Решение: переименуйте файл в index.php или добавьте обработку HTML через настройку settings.json: "extension_xml": ["html"] (список расширений, обрабатываемых PHP).
Как создать нативное GUI-приложение на PHP без браузерного движка?
Вариант: PHP-GTK (расширение)
PHP-GTK - это расширение PHP, использующее библиотеку GTK+ для построения оконного интерфейса. Требует компиляции расширения из исходников или использования готового сборщика (php-gtk2).
<?php
define('GTK_STYLE_PROVIDER_PRIORITY_APPLICATION', 600);
$window = new GtkWindow();
$window->set_title('PHP-GTK пример');
$window->set_default_size(400, 200);
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$label = new GtkLabel('Привет из PHP-GTK!');
$window->add($label);
$window->show_all();
Gtk::main();
?>Php learning (обучение php)
Запуск: php -d extension=php_gtk2.so script.php (Linux) или с соответствующим DLL на Windows.
Проблема: расширение не загружается, ошибка «Unable to load dynamic library»
Причина: отсутствие установленной библиотеки GTK+ или несовместимость версий. На Windows требуется установка пакета GTK+ Runtime.
Решение: скачать и установить GTK+ All-in-one bundle с GitHub. На Linux - sudo apt install libgtk-3-dev php-gtk.
Цель: полный контроль над интерфейсом, возможность использования системных виджетов, работа без веб-сервера. Подходит для системных утилит и приложений с низким потреблением памяти.
Как использовать PHP только как бэкенд, а интерфейс сделать на HTML/JS без отдельного браузера?
Вариант: встроенный веб-сервер PHP + WebView
Используется класс WebView2 (Windows) или WKWebView (macOS), встроенный в нативное приложение (например, на C#). PHP-скрипт запускается как локальный сервер, WebView отображает его содержимое.
Пример на C# с WebView2:
// Запуск PHP-сервера
system("start /B php -S localhost:8080 -t D:\\myapp\\www");
// Создание WebView2
webView21.Source = new Uri("http://localhost:8080");
Php учебник (учебник по php)
Недостаток: требуется среда выполнения .NET или компиляция дополнительного кода. Для кросс-платформенности подходит NW.js или Electron с вызовом PHP-процесса.
Проблема: WebView не может загрузить локальный адрес из-за политики безопасности
Решение: настроить WebView на разрешение локальных URL (localhost обычно разрешён). В WebView2 используйте CoreWebView2EnvironmentOptions с параметром AdditionalBrowserArguments.
Цель: разделение интерфейса и логики, использование современных фронтенд-фреймворков (React, Vue) с PHP-бэкендом, упаковка в настольное приложение.
Как объединить PHP с Electron для создания десктопного приложения с веб-интерфейсом?
Вариант: Electron + PHP как внешний процесс
Основное приложение Electron (Node.js) запускает PHP-сервер в фоновом процессе и открывает окно с URL этого сервера.
// main.js (Electron)
const { app, BrowserWindow } = require('electron');
const { spawn } = require('child_process');
let phpServer;
app.on('ready', () => {
phpServer = spawn('php', ['-S', 'localhost:8080', '-t', 'www'], {
cwd: __dirname
});
const win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('http://localhost:8080');
app.on('before-quit', () => {
phpServer.kill();
});
});Apis php (api на php)
Файлы PHP и HTML находятся в подпапке www. Приложение упаковывается с помощью electron-builder, а PHP интерпретатор включается в ресурсы.
Проблема: порт 8080 может быть занят другим процессом
Решение: перед запуском проверить доступность порта и выбрать случайный свободный. Используйте модуль get-port или обёртку php-server.
Цель: кроссплатформенность, доступ к системным API через Node.js, привычная среда для веб-разработчиков. Подходит для сложных приложений с большим количеством зависимостей.
Как использовать PHP через FFI (Foreign Function Interface) для прямого вызова системных библиотек?
Вариант: PHP FFI с библиотеками GUI (например, IUP)
Начиная с PHP 7.4, поддерживается FFI. Можно подключать разделяемые библиотеки на C, например, библиотеку IUP для портабельного GUI.
<?php
// Загрузка библиотеки IUP (libiup.dll или libiup.so)
$ffi = FFI::cdef('
typedef void* Ihandle;
Ihandle* IupOpen(int *argc, char ***argv);
void IupClose();
Ihandle* IupLabel(const char *title);
Ihandle* IupSetAttribute(Ihandle *ih, const char *name, const char *value);
int IupShow(Ihandle *ih);
void IupMainLoop();
', 'libiup.so');
$ffi->IupOpen(FFI::addr(FFI::new('int')), FFI::addr(FFI::new('void*')));
$label = $ffi->IupLabel('Привет из FFI!');
$ffi->IupSetAttribute($label, 'TITLE', 'Пример');
$ffi->IupShow($label);
$ffi->IupMainLoop();
$ffi->IupClose();
?>
Требуется наличие библиотеки IUP (предварительно установленной). Подходит для простых оконных приложений без сложных виджетов.
Проблема: FFI не найден или не поддерживается
Причина: PHP собран без поддержки FFI. Включите расширение ffi и установите ffi.enable=true в php.ini.
Цель: максимальная производительность без лишних прослоек, но требует знаний C и низкоуровневого программирования.
Расширенные примеры использования PHP Desktop
1. Взаимодействие с базой данных SQLite
Создадим простейший список задач (to-do list) с хранением в SQLite.
<?php
// db.php - создание таблицы и добавление записей
$db = new SQLite3('tasks.db');
$db->exec('CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY, text TEXT, done INTEGER DEFAULT 0)');
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add'])) {
$stmt = $db->prepare('INSERT INTO tasks (text) VALUES (:text)');
$stmt->bindValue(':text', $_POST['text'], SQLITE3_TEXT);
$stmt->execute();
header('Location: index.php');
exit;
}
$tasks = $db->query('SELECT * FROM tasks');
?>
<!DOCTYPE html>
<html>
<head><title>Задачи</title></head>
<body>
<h2>Список задач</h2>
<form method="post">
<input type="text" name="text" required>
<button type="submit" name="add">Добавить</button>
</form>
<ul>
<?php while ($task = $tasks->fetchArray(SQLITE3_ASSOC)): ?>
<li><?= htmlspecialchars($task['text']) ?></li>
<?php endwhile; ?>
</ul>
</body>
</html>
Результат: приложение запускается, позволяет добавлять задачи и отображает их. Файл базы данных tasks.db создаётся в папке www.
2. Использование пользовательского протокола (php://)
PHP Desktop поддерживает собственные протоколы для загрузки ресурсов из виртуальной файловой системы.
// settings.json - настройка протокола
{
"website": {
"virtual_fs": "app://local/"
}
}
В PHP-коде можно использовать file_get_contents('app://local/config.json') для чтения файлов, встроенных в приложение.
<?php
$config = json_decode(file_get_contents('app://local/config.json'), true);
echo "Приложение: " . $config['app_name'];
?>
3. Вызов PHP-функции из JavaScript через AJAX
Архитектура PHP Desktop позволяет выполнять AJAX-запросы к серверной части.
<!-- index.html -->
<script>
function getTime() {
fetch('/ajax.php?action=time')
.then(response => response.text())
.then(data => document.getElementById('time').innerText = data);
}
</script>
<button onclick="getTime()">Получить время</button>
<p id="time"></p>
<?php // ajax.php
if (isset($_GET['action']) && $_GET['action'] === 'time') {
echo date('Y-m-d H:i:s');
exit;
}
?>
4. Упаковка приложения в один исполняемый файл
Используйте phpdesktop-builder (скрипт на Python) для создания .exe с включёнными ресурсами.
python builder.py --php-version 8.2 --app-dir ./myapp --output myapp.exe
После этого приложение не требует отдельного PHP интерпретатора - всё встроено.
5. Интеграция с WebSocket
PHP Desktop включает поддержку WebSocket через встроенный сервер. Используйте библиотеку Ratchet.
// composer.json в папке www
{
"require": {
"cboden/ratchet": "^0.4"
}
}
<?php
// server.php - запускается отдельно или через task.json
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
require 'vendor/autoload.php';
$ws = new WsServer(new \MyApp\Chat());
$server = IoServer::factory(
new HttpServer($ws),
8081
);
$server->run();
?>
Клиентская часть подключается к ws://localhost:8081.
6. Работа с файловой системой (чтение/запись конфигурации)
По умолчанию PHP имеет доступ к файловой системе. Рекомендуется хранить данные в папке %APPDATA% (Windows) или аналогичной.
<?php
$configDir = getenv('APPDATA') . DIRECTORY_SEPARATOR . 'MyApp';
if (!is_dir($configDir)) {
mkdir($configDir, 0777, true);
}
$configFile = $configDir . DIRECTORY_SEPARATOR . 'settings.json';
$settings = ['theme' => 'dark', 'language' => 'ru'];
file_put_contents($configFile, json_encode($settings, JSON_PRETTY_PRINT));
?>
7. Использование PHP Desktop с Vue.js или React
Поместите собранный фронтенд в папку www. PHP будет обрабатывать API-запросы.
<!-- www/index.html (точка входа для SPA) -->
<div id="app"></div>
<script src="app.js"></script>
<script>
// Пример fetch-запроса к PHP
fetch('/api/hello.php').then(r => r.text()).then(console.log);
</script>
В settings.json укажите "startup_file": "index.html", а все PHP-роуты определятся в .htaccess (используйте встроенный PHP-роутер).
8. Отладка с помощью консоли браузера
В PHP Desktop можно открыть инструменты разработчика Chrome (по умолчанию F12). Убедитесь, что в настройках settings.json разрешён инспектор:
{
"webengine": {
"allow_devtools": true
}
}