Crie aplicativos leves e instaláveis escritos em HTML, CSS, JavaScript e PHP para os sistemas operacionais Windows, Mac e Linux Desktop.

O que pode ser criado com o PHP App Server são aplicativos de software reais e instaláveis que levam uma fração do tempo para criar quando comparados ao desenvolvimento de aplicativos de desktop tradicional. Vá de Idea/conceito para implantação total em 1/10 da hora e suporta todos os principais sistemas operacionais da área de trabalho com apenas uma base de código.

O PHP App Server é um servidor web totalmente comuns e extensíveis, escrito no PHP, com recursos personalizados especialmente projetados para serem usados em um ambiente de sistema operacional tradicional. Quando o usuário executa o software através do menu Iniciar, iniciador de aplicativos etc., o software inicia o servidor e inicia o navegador preferido do usuário para acessar o aplicativo. O PHP alimenta o back-end, enquanto o navegador da Web lida com todos os detalhes da questão da exibição da interface do usuário. Os scripts do instalador pronto simplificam o processo de criação de pacotes de liberação final para entrega nos sistemas de computador do seu usuário.
Faça o download ou clone a versão mais recente do software. Ao clonar, use um garfo e crie uma ramificação para o seu aplicativo antes de iniciar o desenvolvimento. Isso evita que substitua acidentalmente seu software sempre que você busca atualizações upstream para o próprio servidor de aplicativos PHP.
Para o restante deste guia, supõe -se que uma versão recente do PHP esteja instalada. Existem muitas maneiras de fazer isso acontecer.
De uma linha de comando, execute o seguinte para obter uma lista de opções de linha de comando:
php server.php -?
Inicie um servidor da web na porta 9002 executando:
php server.php -port=9002
A estrutura de diretório do servidor de aplicativos PHP é a seguinte:
server.php para operar. Crie um arquivo index.php no diretório 'www':
<?php
phpinfo ();Conecte -se ao servidor em execução com seu navegador da web em:
http://127.0.0.1:9002/
A saída de phpinfo() é exibida no navegador e o resultado da solicitação é gravado na linha de comando.
Altere o URL para:
http://127.0.0.1:9002/api/v1/account/info
O mesmo arquivo index.php é executado.
Renomeie ou copie o arquivo index.php para api.php e recarregue a página. Agora api.php está sendo chamado. O recurso de diretório virtual do PHP App Server é algo que você pode achar útil ao desenvolver seu aplicativo.
Os aplicativos de software instalados não podem gravar em 'www'. Os aplicativos geralmente são instalados por um usuário privilegiado no sistema, mas a pessoa que executa o software geralmente não tem permissões suficientes para gravar no diretório 'www'. Esta é uma consideração importante a ser lembrada ao desenvolver um aplicativo de software usando o PHP App Server. Felizmente, existe uma solução para esse problema já incorporado ao servidor: raízes de documentos duplos.
Quando o código PHP está executando a partir do diretório 'www' do aplicativo, ele tem acesso a cinco variáveis $_SERVER que são passadas e são exclusivas do ambiente do servidor de aplicativos PHP:
DOCUMENT_ROOT_USER . Também pode ser escrito, mas não pode ser referenciado pelos URLs. Útil para armazenar dados privados para o aplicativo (por exemplo, um banco de dados SQLite).server.php reside). Útil para acessar arquivos no subdiretório support . Quando uma solicitação é feita para o servidor da web, o PHP App Server parece primeiro para arquivos no diretório 'www' do aplicativo. Se não encontrar um arquivo lá, ele verá o arquivo no caminho especificado por DOCUMENT_ROOT_USER .
A gravação de um aplicativo de servidor localhost que depende de um navegador da Web pode resultar em sérias violações de segurança do sistema, desde a perda de controle de dados e danificar o sistema de arquivos do usuário. Desde que o aplicativo seja escrito corretamente, as políticas do navegador da Web geralmente protegem o usuário de sites e usuários maliciosos que tentam acessar o conteúdo controlado por servidor de aplicativos PHP.
No entanto, aqui estão alguns importantes, selecione itens relacionados à segurança que todos os aplicativos de software baseados em servidores de aplicativos PHP devem se defender ativamente (em ordem de importância):
$_SERVER["PAS_USER_FILES"] ou um local definido pelo usuário para armazenar dados sensíveis ao usuário em vez de $_SERVER["DOCUMENT_ROOT_USER"] . Sempre pergunte ao usuário o que fazer se eles considerarem algo sensível (por exemplo, perguntar pode ser tão simples quanto exibir uma caixa de seleção para o usuário). Indivíduos centrados na privacidade geralmente falam o que pensam.$_SERVER["PAS_SECRET"] Combinado com o pacote de administrador Cubiclesoft ou outras estruturas de aplicativos ajudam a lidar com esse problema. As extensões do servidor também geralmente exigem um token de autenticação com base em $_SERVER["PAS_SECRET"] .Existem muitas outras considerações de segurança que estão na lista dos 10 melhores do OWASP e na lista de ataques OWASP para ter em mente, mas esses são os grandes.
O PHP App Server inclui uma extensão poderosa do servidor e dois SDKs para facilitar a facilidade e o gerenciamento e o monitoramento dos processos de longa execução do PHP e do JavaScript. Os processos iniciados são executados como o usuário que o PHP App Server está em execução, mas não é limitado por tempos limite ou limites de memória como solicitações regulares de CGI/FastCGI. Os processos de execução podem ser monitorados ativamente e até interagir com o navegador da web através do JavaScript SDK incluído.

Os scripts de longa duração devem ser armazenados idealmente em um subdiretório de 'scripts' do diretório 'suporte' do servidor de aplicativos PHP principal. Dessa forma, eles estão longe da raiz principal da web, mas o aplicativo ainda pode encontrá -los via $_SERVER["PAS_ROOT"] .
Aqui está um exemplo de iniciar um script PHP chamado 'test.php' usando o 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. " ;
?>Cada processo recebe uma tag, que permite que vários processos de execução sejam agrupados por tag. No exemplo acima, a tag é chamada de "demonstração". O Javacsript SDK pode ser usado posteriormente para mostrar apenas processos que usam uma tag específica:
<?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>O PHP SDK simplifica emitindo as dependências CSS e JAVScript necessárias no HTML. O código acima demonstra a configuração de uma conexão do WebSocket com a extensão do servidor de aplicativos PHP e conectando -o a uma instância do TerminalManager para monitorar processos com a tag "Demo". O TerminalManager é uma classe JavaScript incluída que cria e gerencia automaticamente um ou mais terminais executivos (também incluídos) com base nos critérios de entrada. Nesse caso, o TerminalManager anexará automaticamente a qualquer processo criado com uma tag "demonstração". Um Execterminal é o seguinte:

Cada Execterminal encerra uma instância do terminal XTERM.JS com recursos adicionais:
E mais.
Observe que o TerminalManager e o ExecTerminal não são necessários para o gerenciamento de processos de longo prazo, mas eles lidam com alguns cenários comuns. O código de exemplo acima apenas arranha a superfície do que pode ser feito.
Aqui está a lista completa das opções do TerminalManager:
A classe Xterm PHP incluída oferece controle perfeito e simplificado sobre a saída de um script de longa duração para o Execterminal Compatível com Xterm no navegador. Não há necessidade de lembrar os códigos de escape da ANSI. Aqui está um exemplo de script:
<?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" ;
?>Por fim, se você usar o Cubiclesoft Admin Pack ou FlexForms para criar seu aplicativo, o PHP SDK inclui a integração do FlexForms nativo (ou seja, não é necessário escrever 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 );
?> Escrever uma extensão requer um pouco de conhecimento sobre como o servidor de aplicativos PHP funciona: as extensões são carregadas desde o início durante a inicialização para que possam se envolver na sequência de inicialização, se precisar (principalmente apenas para extensões relacionadas à segurança). Depois que o servidor da web é iniciado, todas as solicitações da Web passam pela lista de extensões e pergunta: "Você pode lidar com essa solicitação?" Se uma extensão responder na afirmação (ou seja, retornar verdadeiro), o restante da solicitação será transmitido para a extensão para manipular.
Como as extensões são executadas diretamente alinhadas com o servidor principal, elas recebem um aumento significativo de desempenho e podem fazer coisas como responder sobre os processos de WebSocket ou iniciar os processos de longa duração que normalmente seriam mortos após 30 segundos pelo caminho PHP normal.
No entanto, esses benefícios vêm com duas grandes desvantagens. A primeira é que, se uma extensão aumenta uma exceção não capturada ou trava, leva todo o servidor da Web. A segunda é que fazer alterações de código em uma extensão requer reiniciar o servidor da web para testar as alterações, o que pode ser um pouco com um aborrecimento. Em geral, o caminho normal 'www' é suficiente para a maioria das necessidades e as extensões são para segmentos ocasionais de lógica especializada.
A extensão de token de segurança incluída é um excelente ponto de partida para criar uma extensão que pode lidar adequadamente com solicitações. A extensão do token de segurança é bastante curta, bem contratada e obras.
O servidor pressupõe que o nome do arquivo faça parte do nome da classe. Qualquer que seja o nome do arquivo PHP, o nome da classe deve seguir o ADMP, caso contrário, o servidor de aplicativos PHP não conseguirá carregar a extensão. Os nomes de extensão devem começar com um número, o que indica a ordem esperada para chamar a extensão.
As variáveis disponíveis para scripts normais de PHP também estão disponíveis para extensões por meio da variável Global $baseenv (por exemplo, $baseenv["DOCUMENT_ROOT_USER"] e $baseenv["PAS_USER_FILES"] ). Por favor, não altere os valores de $baseenv , pois isso afetará negativamente o restante do aplicativo.
Sempre use o ProcessHelper::StartProcess() Função estática ao iniciar processos externos e de longa execução dentro de uma extensão. A classe ProcessHelper foi projetada para iniciar processos não bloqueadores em segundo plano em todas as plataformas. Observe que a maneira preferida de iniciar processos de longa execução é usar a extensão de processos de longa duração.
Para determinadas tarefas, é importante dizer ao PHP App Server para sair. Por exemplo, ao atualizar um aplicativo PHP App Server no Windows, o próprio PHP precisa ser atualizado e, portanto, não pode estar sendo executado durante a atualização. Também é geralmente um bom comportamento sair de um aplicativo pouco tempo depois que a última guia do navegador estiver fechada.
Existem dois métodos disponíveis para desencadear o término precoce do servidor:
/exit-app/ e envie um authtoken válido e um delay em um objeto JSON que especifica o número de segundos para aguardar o término do servidor. Uma vez usado, todas as páginas do aplicativo devem se conectar ao /exit-app/ para manter o servidor vivo. Recomenda -se um atraso mínimo de 3 segundos. Os navegadores da Web tendem a soltar conexões do WebSocket assim que saem da página ou a guia é fechada.X-Exit-App na resposta de um script PHP. O valor do cabeçalho é o número inteiro de segundos para esperar para encerrar o servidor. Recomenda -se um atraso mínimo de 3 segundos. Este cabeçalho especial não é passado para o navegador da web, mas tratado internamente.Exemplo de código PHP para o método de extensão de aplicativo de saída:
<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>Exemplo de código PHP para o método do cabeçalho:
<?php
// User clicked an "Exit application" link or something.
header ( " X-Exit-App: 3 " );
?>A extensão é um método mais confiável de detectar que todas as guias do navegador para o aplicativo foram fechadas. No entanto, se o aplicativo não puder suportar a extensão por algum motivo, use o método do cabeçalho. O método do cabeçalho é melhor usado nas páginas onde faz sentido (por exemplo, uma página com informações de atualização).
Antes de executar os vários scripts que geram pacotes de instaladores, vários arquivos precisam ser criados, renomeados e/ou modificados. Cada arquivo que começa com "YourApp" precisa ser renomeado para o nome do seu aplicativo, de preferência restrito a todos os AZ e hífens minúsculos. Isso precisa ser feito para que as atualizações do software não substituam seu trabalho acidentalmente e para que todos os usuários intrometidos cutucam a estrutura do diretório, veja o nome real do aplicativo em vez de "YourApp".
O arquivo 'YourApp.phpapp' é um arquivo php que executa a sequência de inicialização de aplicativos real de iniciar o servidor da web (Server.php) e, em seguida, inicia o navegador da web do usuário. Existe uma matriz $options no arquivo que deve ser modificada para as necessidades do seu aplicativo:
As três últimas opções destinam -se a cenários altamente especializados. Alterar o 'host' para algo como "127.0.1.1" pode estar bem, mas não use "0.0.0.0" ou ":: 0", que vincula o servidor publicamente à interface de rede. A ligação a um número de 'porta' específico pode parecer uma boa idéia até que os usuários comecem a reclamar de mensagens de erro quando tentam reiniciar o aplicativo.
A opção 'saydelay' é interessante. A parte do servidor do PHP App Server permanecerá até o 'sayDelay' minutos após o último cliente desconectar. O aplicativo deve enviar uma solicitação de "batimentos cardíacos" a cada cinco minutos para garantir que o servidor da Web não se termine antes que o usuário termine usando o aplicativo.
Cada ferramenta de embalagem de plataforma tem suas próprias instruções:
xdg-utils (Gnome, KDE, XFCE, etc. estão tudo bem).Existem alguns problemas de embalagem conhecidos:
Os instaladores e o software do servidor têm alguns contos interessantes por trás deles. Talvez eu compartilhe essas histórias um dia. Por enquanto, aproveite a criação de seu próximo aplicativo no PHP App Server!