Создайте легкие установленные приложения, написанные в HTML, CSS, JavaScript и PHP для операционных систем Windows, Mac и Linux.

То, что можно создать с помощью PHP App Server, - это реальные, установленные программные приложения, которые занимают долю времени для создания по сравнению с традиционной разработкой приложений для настольных компьютеров. Перейдите от идеи/концепции к полному развертыванию в 1/10, в то время и поддерживайте каждую основную ОС настольных компьютеров только одной кодовой базой.

PHP App Server-это полнофункциональный и расширяемый веб-сервер, написанный на PHP с пользовательскими функциями, специально разработанными для использования в традиционной среде настольной ОС. Когда пользователь запускает программное обеспечение через свое меню «Пуск», «Запуск приложения» и т. Д., Программное обеспечение запускает сервер, а затем запускает предпочтительный веб -браузер пользователя для доступа к приложению. PHP питает бэкэнд, в то время как веб-браузер обрабатывает все придуманные детали отображения пользовательского интерфейса. Готовые сценарии установщика упрощают процесс создания окончательных пакетов выпуска для доставки в компьютерные системы вашего пользователя.
Скачать или клонировать последний выпуск программного обеспечения. При клонировании обязательно используйте вилку и создайте филиал для вашего приложения перед началом разработки. Это избегает случайного перезаписи вашего программного обеспечения всякий раз, когда вы получаете обновления вверх по течению для самого сервера приложений PHP.
Для остальной части этого руководства предполагается, что недавняя версия PHP будет установлена. Есть много способов сделать это.
Из командной строки запустите следующее, чтобы получить список параметров командной строки:
php server.php -?
Запустите веб -сервер на порту 9002 с помощью:
php server.php -port=9002
Структура каталога сервера приложений PHP заключается в следующем:
server.php для работы. Создайте файл index.php в каталоге 'www':
<?php
phpinfo ();Подключитесь к запущению сервера с помощью вашего веб -браузера по адресу:
http://127.0.0.1:9002/
Выход phpinfo() отображается в браузере, и результат запроса записывается в командную линию.
Измените URL на:
http://127.0.0.1:9002/api/v1/account/info
Тот же файл index.php работает.
Переименовать или скопировать файл index.php в api.php и перезагрузить страницу. Теперь api.php называют. Функция виртуального каталога сервера приложений PHP - это то, что вы можете найти полезным по мере разработки своего приложения.
Установленные программные приложения не могут записать на «www». Приложения обычно устанавливаются привилегированным пользователем в системе, но у человека, работающего в программном обеспечении, как правило, не будет достаточных разрешений для записи в каталог «www». Это важное соображение, которое следует иметь в виду при разработке программного приложения с использованием сервера приложений PHP. К счастью, есть решение этой проблемы, уже встроенное в сервер: двойные корни документов.
Когда PHP -код выполняется из каталога приложения 'www', он имеет доступ к пять переменных $_SERVER , которые передаются и являются уникальными для среды сервера приложений PHP:
DOCUMENT_ROOT_USER . Также можно записано, но нельзя ссылаться на URL -адреса. Полезно для хранения частных данных для приложения (например, база данных SQLite).server.php ). Полезно для доступа к файлам в подкаталоге support . Когда запрос внесен на веб -сервер, сервер приложений PHP сначала смотрит на файлы в каталоге «www» приложения. Если он не найдет файл там, он проверяет файл в пути, указанный DOCUMENT_ROOT_USER .
Написание приложения Localhost Server, которое полагается на веб -браузер, может привести к серьезным нарушениям безопасности системы, начиная от потери управления данными до повреждения файловой системы пользователя. Пока приложение написано правильно, политики веб -браузера, как правило, защищают пользователя от вредоносных веб -сайтов и пользователей, которые пытаются получить доступ к контенту с управляемым сервером приложений PHP.
Тем не менее, вот несколько важных, выберите элементы, связанные с безопасностью, с которыми все программные приложения на основе сервера приложений PHP должны активно защищаться от (в порядке важности):
$_SERVER["PAS_USER_FILES"] или определенное пользовательское место для хранения конфиденциальных пользовательских данных вместо $_SERVER["DOCUMENT_ROOT_USER"] . Всегда спрашивайте пользователя, что делать, если он может считать что -то чувствительным (например, вопрос может быть таким же простым, как отображение флажона пользователю). Люди, ориентированные на конфиденциальность, обычно высказывают свое мнение.$_SERVER["PAS_SECRET"] в сочетании с пакетом администратора Cubiclesoft или другими прикладными фреймворками, чтобы решить эту проблему. Расширения сервера также обычно требуют токена аутентификации на основе $_SERVER["PAS_SECRET"] .Есть много других соображений безопасности, которые находятся в списке 10 топ -10 OWASP, и в списке атак OWASP также следует помнить, но это большие.
PHP App Server включает в себя мощное расширение сервера и два SDK для облегчения начала, управления и мониторинга продолжительных процессов простыми и безопасными как от PHP, так и от JavaScript. Запуск процессов работает как пользователь, который работает PHP App Server, но не ограничивается таймаутами или ограничениями памяти, такими как обычные запросы CGI/FASTCGI. Запуск процессов может активно контролироваться и даже взаимодействовать с веб -браузером через включенный JavaScript SDK.

В идеале должны быть сохранены долгосрочные сценарии в подкаталоге «Сценарии» из основного каталога «поддержки» приложений PHP. Таким образом, они находятся вдали от основного веб -корня, но приложение все еще может найти их через $_SERVER["PAS_ROOT"] .
Вот пример запуска сценария PHP под названием «test.php» с использованием PHP SDK:
<?php
$ rootpath = str_replace ( "\" , " / " , dirname ( __FILE__ ));
// Load the PHP App Server common functions.
require_once $ _SERVER [ " PAS_ROOT " ] . " /support/process_helper.php " ;
require_once $ _SERVER [ " PAS_ROOT " ] . " /support/pas_functions.php " ;
$ cmd = escapeshellarg ( PAS_GetPHPBinary ());
$ cmd .= " " . escapeshellarg ( realpath ( $ _SERVER [ " PAS_ROOT " ] . " /support/scripts/test.php " ));
$ options = array (
// "rules" => array(
// "start" => time() + 5,
// "maxqueued" => 3
// ),
// "stdin" => false,
// "dir" => $_SERVER["PAS_ROOT"] . "/support/scripts/",
// "env" => ProcessHelper::GetCleanEnvironment(),
// "extraenv" => array("PASSWORD" => "supersecret"),
// "extra" => array(
// "title" => "Custom window title",
// "inputmode" => "readline"
// )
);
// Start the process.
require_once $ rootpath . " /support/pas_run_process_sdk.php " ;
$ rp = new PAS_RunProcessSDK ();
$ result = $ rp -> StartProcess ( " demo " , $ cmd , $ options );
if (! $ result [ " success " ]) echo " An error occurred while starting a long-running process. " ;
echo " Done. " ;
?>Каждому процессу дается тег, который позволяет сгруппировать несколько запущенных процессов с помощью тега. В приведенном выше примере тег называется «демонстрация». Javacsript SDK может позже использоваться для показа только процессов, которые используют конкретный тег:
<?php
header ( " Content-Type: text/html; charset=UTF8 " );
?>
<!DOCTYPE html>
<html>
<body>
<?php
$ rootpath = str_replace ( "\" , " / " , dirname ( __FILE__ ));
require_once $ rootpath . " /support/pas_run_process_sdk.php " ;
PAS_RunProcessSDK:: OutputCSS ();
PAS_RunProcessSDK:: OutputJS ();
?>
<div id="terminal-manager"></div>
<script type="text/javascript">
// NOTE: Always put Javascript RunProcesSDK and TerminalManager class instances in a Javascript closure like this one to limit the XSRF attack surface.
(function() {
// Establish a new connection with a compatible WebSocket server.
var runproc = new RunProcessSDK(' <?= PAS_RunProcessSDK:: GetURL () ?> ', false, ' <?= PAS_RunProcessSDK:: GetAuthToken () ?> ');
// Debugging mode dumps incoming and outgoing packets to the web browser's debug console.
runproc.debug = true;
// Establish a new terminal manager instance.
var elem = document.getElementById('terminal-manager');
// Automatically attach to all channels with the 'demo' tag.
var options = {
tag: 'demo'
};
var tm = new TerminalManager(runproc, elem, options);
})();
</script>
</body>
</html>PHP SDK упрощает излучение необходимых зависимостей CSS и Javscript в HTML. Приведенный выше код демонстрирует настройку подключения к WebSocket к расширению сервера приложений PHP и подключение к экземпляру TerminalManager для мониторинга процессов с тегом «демонстрация». TerminalManager - это включенный класс JavaScript, который автоматически создает и управляет одним или несколькими ExecTerminals (также включенным) на основе критериев ввода. В этом случае TerminalManager автоматически прикрепляется к любому процессу, созданному с помощью тега «демонстрации». ExecTerminal выглядит так:

Каждый ExecTerminal завершает экземпляр терминала XTERM.JS с дополнительными функциями:
И еще.
Обратите внимание, что TerminalManager и ExecTerminal не требуются для управления продолжительными процессами, но они справляются с несколькими распространенными сценариями. Пример кода выше только царапает поверхность того, что можно сделать.
Вот полный список вариантов TerminalManager:
Включенный класс XERM PHP предлагает плавный и упрощенный контроль над выходом от долгосрочного сценария до XERM-совместимого ExecTerminal в браузере. Не нужно помнить коды побега ANSI. Вот пример сценария:
<?php
if (! isset ( $ _SERVER [ " argc " ]) || ! $ _SERVER [ " argc " ])
{
echo " This file is intended to be run from the command-line. " ;
exit ();
}
$ rootpath = str_replace ( "\" , " / " , dirname ( __FILE__ ));
require_once $ rootpath . " /../xterm.php " ;
for ( $ x = 0 ; $ x < 5 ; $ x ++)
{
echo " Test: " . ( $ x + 1 ) . "n" ;
sleep ( 1 );
}
echo " That's boring. Let's... " ;
sleep ( 1 );
XTerm:: SetItalic ();
echo " spice it up! n" ;
XTerm:: SetItalic ( false );
sleep ( 1 );
$ palette = XTerm:: GetBlackOptimizedColorPalette ();
for ( $ x = 5 ; $ x < 10 ; $ x ++)
{
$ num = mt_rand ( 17 , 231 );
XTerm:: SetForegroundColor ( $ palette [ $ num ]);
echo " Test: " . ( $ x + 1 ) . " (Color " . $ palette [ $ num ] . " ) n" ;
sleep ( 1 );
}
XTerm:: SetForegroundColor ( false );
XTerm:: SetTitle ( " Changing the title... " );
usleep ( 250000 );
XTerm:: SetTitle ( " Changing the title...like " );
usleep ( 250000 );
XTerm:: SetTitle ( " Changing the title...like a " );
usleep ( 250000 );
XTerm:: SetTitle ( " Changing the title...like a BOSS! " );
usleep ( 500000 );
echo "n" ;
echo " Enter some text: " ;
$ line = rtrim ( fgets ( STDIN ));
XTerm:: SetBold ();
echo " Here's what you wrote: " . $ line . "nn" ;
XTerm:: SetBold ( false );
echo " [Switching to 'readline_secure' mode] nn" ;
XTerm:: SetCustomInputMode ( ' readline_secure ' );
echo " Enter some more text: " ;
XTerm:: SetColors ( 0 , 0 );
$ line = rtrim ( fgets ( STDIN ));
XTerm:: SetColors ( false , false );
XTerm:: SetCustomInputMode ( ' readline ' );
XTerm:: SetBold ();
echo " Here's what you wrote: " . $ line . "nn" ;
XTerm:: SetBold ( false );
echo " Done. n" ;
?>Наконец, если вы используете пакет администраторов Cubiclesoft или Flexforms для создания вашего приложения, PHP SDK включает в себя Native Flexforms Integration (то есть не нужно писать JavaScript/HTML):
<?php
// Admin Pack and FlexForms integration.
require_once " support/pas_run_process_sdk.php " ;
$ contentopts = array (
" desc " => " Showing all long-running processes with the 'demo' tag. " ,
" fields " => array (
array (
" type " => " pas_run_process " ,
// "debug" => true,
" options " => array (
" tag " => " demo "
)
)
)
);
BB_GeneratePage ( " Process Demo " , $ menuopts , $ contentopts );
?> Написание расширения требует небольшого знания о том, как работает сервер приложений PHP: расширения загружаются на ранних этапах запуска, чтобы они могли участвовать в последовательности запуска, если им нужно (в основном только для расширений, связанных с безопасностью). После того, как веб -сервер начался, каждый веб -запрос проходит список расширений и спрашивает: «Можете ли вы обработать этот запрос?» Если расширение отвечает в утвердительном утверждении (то есть возвращает true), то остальная часть запроса передается в продление для обработки.
Поскольку расширения запускаются непосредственно в соответствии с основным сервером, они получают значительный повышение производительности и могут делать такие вещи, как реагирование на WebSocket или запуск длительных процессов, которые обычно будут убиты после 30 секунд в результате нормального пути PHP.
Тем не менее, эти преимущества имеют два основных недостатка. Во -первых, если расширение повышает необработанное исключение или иным образом сбои, он берет на себя весь веб -сервер. Во -вторых, внесение изменений кода в расширение требует перезапуска веб -сервера для проверки изменений, которые могут быть немного хлопотами. В целом, нормального пути «www» достаточно для большинства потребностей, и расширения предназначены для случайных сегментов специализированной логики.
Включенное расширение токена безопасности является отличной отправной точкой для создания расширения, которое может правильно обрабатывать запросы. Расширение токенов безопасности довольно короткое, хорошо подготовленное и работает.
Сервер предполагает, что имя файла является частью имени класса. Как бы ни назвал файл PHP, имя класса внутри должно следовать примеру, в противном случае сервер приложений PHP не сможет загрузить расширение. Имена расширения должны начинаться с номера, который указывает на ожидаемый порядок, в котором можно было бы вызвать расширение.
Переменные, доступные для обычных скриптов PHP, также доступны для расширений через глобальную переменную $baseenv (например, $baseenv["DOCUMENT_ROOT_USER"] и $baseenv["PAS_USER_FILES"] ). Пожалуйста, не изменяйте значения $baseenv , так как это негативно повлияет на оставшуюся часть приложения.
Всегда используйте статическую функцию ProcessHelper::StartProcess() при запуске внешних, длительных процессов внутри расширения. Класс процессов предназначен для запуска неблокирующих процессов на фоне на всех платформах. Обратите внимание, что предпочтительным способом запуска длительных процессов является использование длительного расширения процессов.
Для определенных задач важно указать серверу приложений PHP. Например, при обновлении приложения Server App Server PHP в Windows необходимо обновлять сам PHP и, следовательно, не может работать во время обновления. В целом, это также хорошее поведение выйти из приложения вскоре после того, как последняя вкладка браузера закрыта.
Существует два доступных метода для запуска досрочного завершения сервера:
/exit-app/ и отправьте действительный authtoken и delay в объекте JSON, который указывает количество секунд, чтобы ждать, чтобы завершить сервер. После использования каждая страница приложения должна подключаться к /exit-app/ для поддержания сервера. Рекомендуется минимальная задержка 3 секунды. Веб -браузеры, как правило, отказываются от соединений WebSocket, как только они покидают страницу, или вкладка закрыта.X-Exit-App в ответ сценария PHP. Значение заголовка - это целое число секунд, чтобы ждать, чтобы завершить сервер. Рекомендуется минимальная задержка 3 секунды. Этот специальный заголовок не передается в веб -браузер, но обрабатывается внутри.Пример PHP -кода для метода расширения приложения выхода:
<script type="text/javascript">
// NOTE: Always put WebSocket class instances in a Javascript closure like this one to limit the XSRF attack surface.
( function () {
function InitExitApp ()
{
var ws = new WebSocket ((window.location.protocol === ' https: ' ? ' wss:// ' : ' ws:// ' ) + window.location.host + ' /exit-app/ ' );
ws. addEventListener ( ' open ' , function ( e ) {
var msg = {
authtoken: ' <?=hash_hmac("sha256", "/exit-app/", $_SERVER["PAS_SECRET"])?> ' ,
delay: 3
};
ws. send ( JSON . stringify (msg));
});
ws. addEventListener ( ' close ' , function ( e ) {
setTimeout (InitExitApp, 500 );
});
}
InitExitApp ();
})();
</script>Пример PHP -кода для метода заголовка:
<?php
// User clicked an "Exit application" link or something.
header ( " X-Exit-App: 3 " );
?>Расширение является более надежным методом обнаружения того, что все вкладки браузера для приложения были закрыты. Однако, если приложение не может поддержать расширение по какой -то причине, вместо этого используйте метод заголовка. Метод заголовка лучше всего используется на страницах, где это имеет смысл (например, страница с информацией об обновлении).
Перед запуском различных сценариев, которые генерируют пакеты установщиков, необходимо создать, переименовать и изменять различные файлы. Каждый файл, который начинается с «YoutApp», должен быть переименован в имя вашего приложения, предпочтительно ограниченным для всех строчных AZ и дефисов. Это должно быть сделано для того, чтобы обновления программного обеспечения не случайно перезаписывали вашу работу и, чтобы любые любопытные пользователи, прокачающиеся по структуре каталогов, видят фактическое имя приложения вместо «YourApp».
Файл 'yourapp.phpapp' представляет собой файл PHP, который выполняет фактическую последовательность запуска приложения запуска веб -сервера (server.php), а затем запуск веб -браузера пользователя. В файле есть массив $options , который должен быть изменен для потребностей вашего приложения:
Последние три варианта предназначены для высокоспециализированных сценариев. Изменение «хоста» на что -то вроде «127.0.1.1» может быть в порядке, но не используйте «0.0.0.0» или «:: 0», что публично связывает сервер с сетевым интерфейсом. Привязанность к конкретному номеру «порта» может показаться хорошей идеей, пока пользователи не начнут жаловаться на сообщения об ошибках, когда они попытаются перезапустить приложение.
Вариант «quitdelay» интересен. Серверная часть сервера приложений PHP будет оставаться до тех пор, пока они не будут отключены в минуту после отключения последнего клиента. Приложение должно отправлять запрос «сердцебиение» каждые пять минут, чтобы гарантировать, что веб -сервер не будет прекращена до того, как пользователь закончит, используя приложение.
Каждый инструмент упаковки платформы имеет свои собственные инструкции:
xdg-utils (GNOME, KDE, XFCE и т. Д. Все в порядке).Есть некоторые известные проблемы с упаковкой:
У установщиков и программного обеспечения сервера есть несколько интересных сказок. Может, однажды я поделюсь этими историями. На данный момент наслаждайтесь созданием следующего приложения на сервере приложений PHP!