Créez des applications légères et installables écrites en HTML, CSS, JavaScript et PHP pour les systèmes d'exploitation de bureau Windows, Mac et Linux.

Ce qui peut être créé avec le serveur d'applications PHP est de véritables applications logicielles installables qui prennent une fraction du temps à créer par rapport au développement d'applications de bureau traditionnel. Passez de l'idée / concept à un déploiement complet en 1 / 10e le temps et prenez-vous à tous les principaux OS de bureau avec une seule base de code.

Le serveur d'applications PHP est un serveur Web entièrement fonctionnel et extensible écrit en PHP avec des fonctionnalités personnalisées spécialement conçues pour être utilisées dans un environnement de système d'exploitation de bureau traditionnel. Lorsque l'utilisateur exécute le logiciel via son menu de démarrage, son lanceur d'applications, etc., le logiciel démarre le serveur, puis lance le navigateur Web préféré de l'utilisateur pour accéder à l'application. PHP alimente le backend tandis que le navigateur Web gère tous les détails Nitty-Gritty de l'affichage de l'interface utilisateur. Les scripts des installateurs prêts à l'emploi simplifient le processus de création de packages de version finale pour la livraison aux systèmes informatiques de votre utilisateur.
Télécharger ou cloner la dernière version du logiciel. Lors du clonage, assurez-vous d'utiliser une fourche et de créer une branche pour votre application avant de commencer le développement. Cela évite d'écraser accidentellement votre logiciel chaque fois que vous récupérez les mises à jour en amont pour le serveur d'applications PHP lui-même.
Pour le reste de ce guide, une version récente de PHP est supposée être installée. Il existe de nombreuses façons d'y arriver.
À partir d'une ligne de commande, exécutez ce qui suit pour obtenir une liste d'options de ligne de commande:
php server.php -?
Démarrez un serveur Web sur le port 9002 en exécutant:
php server.php -port=9002
La structure du répertoire du serveur d'applications PHP est la suivante:
server.php pour fonctionner. Créez un fichier index.php dans le répertoire «www»:
<?php
phpinfo ();Connectez-vous au serveur en cours d'exécution avec votre navigateur Web à:
http://127.0.0.1:9002/
La sortie de phpinfo() est affichée dans le navigateur et le résultat de la demande est écrit sur la ligne de commande.
Changez l'URL en:
http://127.0.0.1:9002/api/v1/account/info
Le même fichier index.php s'exécute.
Renommer ou copier le fichier index.php dans api.php et recharger la page. Maintenant api.php est appelé. La fonction de répertoire virtuel du serveur d'applications PHP est quelque chose que vous pourriez trouver utile lorsque vous développez votre application.
Les applications logicielles installées ne peuvent pas écrire sur «www». Les applications sont généralement installées par un utilisateur privilégié sur le système, mais la personne qui exécute le logiciel ne disposera généralement pas d'autorisations suffisantes pour écrire dans le répertoire «www». Il s'agit d'une considération importante à garder à l'esprit lors du développement d'une application logicielle à l'aide du serveur d'applications PHP. Heureusement, il existe une solution à ce problème déjà intégré au serveur: Double Racines de document.
Lorsque le code PHP s'exécute à partir du répertoire «www» de l'application, il a accès à cinq variables $_SERVER qui sont passées et sont uniques à l'environnement du serveur d'applications PHP:
DOCUMENT_ROOT_USER . Peut également être écrit mais ne peut pas être référencé par les URL. Utile pour stocker des données privées pour l'application (par exemple une base de données SQLite).server.php ). Utile pour accéder aux fichiers dans le sous-répertoire support . Lorsqu'une demande est présentée au serveur Web, le serveur d'applications PHP recherche d'abord les fichiers du répertoire «www» de l'application. S'il n'y trouve pas de fichier, il vérifie ensuite le fichier dans le chemin spécifié par DOCUMENT_ROOT_USER .
La rédaction d'une application de serveur localhost qui s'appuie sur un navigateur Web peut entraîner de graves violations de sécurité du système, allant de la perte de contrôle des données à la dommage au système de fichiers de l'utilisateur. Tant que l'application est écrite correctement, les stratégies du navigateur Web protégeront généralement l'utilisateur des sites Web et des utilisateurs malveillants qui tentent d'accéder au contenu contrôlé par serveur d'applications PHP.
Cependant, voici quelques éléments importants et sélectionnés liés à la sécurité contre lesquels toutes les applications logicielles basées sur le serveur d'applications PHP doivent défendre activement (par ordre d'importance):
$_SERVER["PAS_USER_FILES"] ou un emplacement défini par l'utilisateur pour stocker des données utilisateur sensibles au lieu de $_SERVER["DOCUMENT_ROOT_USER"] . Demandez toujours à l'utilisateur quoi faire s'il peut considérer que quelque chose est sensible (par exemple, il pourrait être aussi simple que d'afficher une case à l'utilisateur). Les individus centrés sur la vie privée exprimeront généralement leur opinion.$_SERVER["PAS_SECRET"] combinée avec un pack d'administration de Cabiclesoft ou d'autres cadres d'application aident à gérer ce problème. Les extensions de serveur nécessitent également généralement un jeton d'authentification basé sur $_SERVER["PAS_SECRET"] .Il existe de nombreuses autres considérations de sécurité qui figurent dans la liste des 10 meilleurs OWASP et la liste des attaques OWASP pour garder à l'esprit, mais ce sont les grands.
Le serveur d'applications PHP comprend une extension de serveur puissante et deux SDK pour faciliter le démarrage, la gestion et la surveillance des processus de longue durée à partir de PHP et JavaScript. Les processus démarrés s'exécutent en tant qu'utilisateur que le serveur d'applications PHP s'exécute comme mais ne sont pas limités par les délais ou les limites de mémoire comme les demandes CGI / FastCGI régulières. Les processus d'exécution peuvent être surveillés activement et même interagi avec le navigateur Web via le SDK JavaScript inclus.

Les scripts de longue durée devraient idéalement être stockés dans un sous-répertoire «scripts» hors du répertoire principal du serveur d'applications PHP '. De cette façon, ils sont loin de la racine Web principale, mais l'application peut toujours les trouver via $_SERVER["PAS_ROOT"] .
Voici un exemple de démarrage d'un script PHP appelé 'test.php' à l'aide du SDK PHP:
<?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. " ;
?>Chaque processus reçoit une balise, ce qui permet de regrouper plusieurs processus en cours d'exécution par balise. Dans l'exemple ci-dessus, la balise est appelée "démo". Le SDK Javacsript peut plus tard être utilisé pour afficher uniquement les processus qui utilisent une balise spécifique:
<?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>Le SDK PHP simplifie l'émission des dépendances CSS et Javscript nécessaires dans le HTML. Le code ci-dessus démontre la configuration d'une connexion WebSocket à l'extension du serveur d'applications PHP et la connecter à une instance TerminalManager pour surveiller les processus avec la balise "Demo". TerminalManager est une classe JavaScript incluse qui crée et gère automatiquement un ou plusieurs exécutions exécutives (également incluses) en fonction des critères d'entrée. Dans ce cas, TerminalManager s'attachera automatiquement à tout processus créé avec une balise "démo". Un execterminal ressemble à ceci:

Chaque execterminal enveloppe une instance de terminal Xterm.js avec des fonctionnalités supplémentaires:
Et plus.
Notez que TerminalManager et Execterminal ne sont pas nécessaires pour gérer les processus de longue durée, mais ils gèrent pas mal de scénarios communs. L'exemple de code ci-dessus ne fait que gratter la surface de ce qui peut être fait.
Voici la liste complète des options TerminalManager:
La classe PHP XTerm incluse offre un contrôle transparent et simplifié sur la sortie d'un script de longue date à l'exécutif compatible xterm dans le navigateur. Pas besoin de se souvenir des codes d'échappement ANSI. Voici un exemple 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" ;
?>Enfin, si vous utilisez un pack d'administration Cabiclesoft ou FlexForm pour créer votre application, le SDK PHP inclut l'intégration Native FlexForm (c'est-à-dire pas besoin d'écrire 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 );
?> L'écriture d'une extension nécessite un peu de connaissances sur le fonctionnement du serveur d'applications PHP: les extensions sont chargées tôt lors du démarrage afin qu'ils puissent s'impliquer dans la séquence de démarrage s'ils en ont besoin (principalement juste pour les extensions liées à la sécurité). Une fois que le serveur Web a commencé, chaque demande Web parcourt la liste des extensions et demande: "Pouvez-vous gérer cette demande?" Si une extension répond dans l'affirmative (c.-à-d. Renvoie vrai), le reste de la demande est transmis à l'extension à gérer.
Étant donné que les extensions sont exécutées directement en ligne avec le serveur principal, ils obtiennent une augmentation significative des performances et peuvent faire des choses telles que répondre sur WebSocket ou démarrer des processus de longue durée qui seraient normalement tués après 30 secondes par le chemin PHP normal.
Cependant, ces avantages comportent deux inconvénients majeurs. La première est que si une extension soulève une exception non revêtue ou autrement se bloque, il emmène l'ensemble du serveur Web avec. La seconde est que la création de modifications de code à une extension nécessite de redémarrer le serveur Web pour tester les modifications, ce qui peut être un peu des tracas. En général, le chemin normal «www» est suffisant pour la plupart des besoins et les extensions concernent des segments occasionnels de logique spécialisée.
L'extension de jeton de sécurité incluse est un excellent point de départ pour construire une extension qui peut gérer correctement les demandes. L'extension de jeton de sécurité est assez courte, bien éveillée et fonctionne.
Le serveur suppose que le nom de fichier fait partie du nom de classe. Quel que soit le fichier PHP nommé, le nom de classe à l'intérieur doit suivre le pas, sinon le serveur d'applications PHP ne parviendra pas à charger l'extension. Les noms d'extension doivent commencer par un nombre, ce qui indique l'ordre attendu dans lequel appeler l'extension.
Les variables disponibles pour les scripts PHP normaux sont également disponibles pour les extensions via la variable globale $baseenv (par exemple $baseenv["DOCUMENT_ROOT_USER"] et $baseenv["PAS_USER_FILES"] ). Veuillez ne pas modifier les valeurs $baseenv car cela affectera négativement le reste de l'application.
Utilisez toujours la fonction statique ProcessHelper::StartProcess() lors du démarrage de processus externes à long terme à l'intérieur d'une extension. La classe ProcessHelper est conçue pour démarrer des processus non bloquants en arrière-plan sur toutes les plates-formes. Notez que la façon préférée de démarrer des processus à long terme est d'utiliser l'extension des processus de longue date.
Pour certaines tâches, il est important de dire au serveur d'applications PHP de quitter. Par exemple, lors de la mise à niveau d'une application de serveur d'applications PHP sur Windows, PHP lui-même doit être mis à jour et ne peut donc pas être exécuté pendant la mise à niveau. Il est également généralement un bon comportement de quitter une application pas trop longtemps après la fermeture de l'onglet Navigateur.
Il existe deux méthodes disponibles pour déclencher la résiliation précoce du serveur:
/exit-app/ et envoyer un authtoken valide et un delay dans un objet JSON qui spécifie le nombre de secondes à attendre pour résilier le serveur. Une fois utilisé, chaque page de l'application doit se connecter à /exit-app/ pour maintenir le serveur en vie. Un délai minimum de 3 secondes est recommandé. Les navigateurs Web ont tendance à supprimer les connexions WebSocket dès qu'ils quittent la page ou que l'onglet est fermé.X-Exit-App dans la réponse d'un script PHP. La valeur de l'en-tête est le nombre entier de secondes à attendre pour résilier le serveur. Un délai minimum de 3 secondes est recommandé. Cet en-tête spécial n'est pas transmis au navigateur Web mais géré en interne.Exemple de code PHP pour la méthode d'extension de sortie de l'application:
<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>Exemple de code PHP pour la méthode d'en-tête:
<?php
// User clicked an "Exit application" link or something.
header ( " X-Exit-App: 3 " );
?>L'extension est une méthode plus fiable de détection que tous les onglets de navigateur à l'application ont été fermés. Cependant, si l'application n'est pas en mesure de prendre en charge l'extension pour une raison quelconque, utilisez plutôt la méthode d'en-tête. La méthode d'en-tête est mieux utilisée sur les pages où elle a du sens (par exemple, une page avec des informations de mise à niveau).
Avant d'exécuter les différents scripts qui génèrent des packages d'installation, divers fichiers doivent être créés, renommés et / ou modifiés. Chaque fichier qui commence par "YourApp" doit être renommé au nom de votre application, de préférence limité à tous les AZ et traits de traits minuscules. Cela doit être fait afin que les mises à jour du logiciel n'écrasent pas accidentellement votre travail et que tous les utilisateurs fouettes qui poussent autour de la structure du répertoire voient le nom réel de l'application au lieu de "votreapp".
Le fichier 'yourapp.phpapp' est un fichier PHP qui effectue la séquence de démarrage de l'application réelle du démarrage du serveur Web (Server.php), puis de lancement du navigateur Web de l'utilisateur. Il existe un tableau $options dans le fichier qui doit être modifié pour les besoins de votre application:
Les trois dernières options sont destinées à des scénarios hautement spécialisés. Changer «hôte» en quelque chose comme «127.0.1.1» peut être correct mais n'utilisez pas »0.0.0.0» ou »ou» :: 0 », qui lie publiquement le serveur à l'interface réseau. La liaison à un «port» spécifique peut sembler une bonne idée jusqu'à ce que les utilisateurs commencent à se plaindre des messages d'erreur lorsqu'ils essaient de redémarrer l'application.
L'option «Quitdelay» est intéressante. La partie du serveur du serveur d'applications PHP restera jusqu'à ce que «QUITDELAY» les minutes après la déconnexion du dernier client. L'application doit envoyer une demande de "rythme cardiaque" toutes les cinq minutes pour garantir que le serveur Web ne se terminera pas avant la fin de l'utilisateur à l'aide de l'application.
Chaque outil d'emballage de plate-forme a ses propres instructions:
xdg-utils (Gnome, KDE, XFCE, etc. sont très bien).Il y a des problèmes d'emballage connus:
Les installateurs et le logiciel du serveur ont des contes intéressants derrière eux. Peut-être que je partagerai ces histoires un jour. Pour l'instant, profitez de la construction de votre prochaine application dans PHP App Server!