Utiliser les archives Phar
Utiliser les archives Phar : Introduction Les archives Phar sont identiques dans le concept aux archives JAR de Java, mais sont conçues plus spécifiquement pour les besoins et la flexibilité des applications PHP. Une archive Phar est utilisée pour distribuer une application PHP complète ou une bibliothèque sous forme d'un fichier unique. Une application sous forme d'archive Phar est utilisée exactement de la même façon que n'importe quelle autre application PHP : L'utilisation d'une bibliothèque sous forme d'archive Phar est la même que n'importe quelle autre bibliothèque PHP : ]]> Le flux phar fournit le cœur de l'extension phar, et est décrit en détails ici. Le flux phar permet l'accès aux fichiers contenus dans une archive phar via les fonctions standards de fichier fopen, opendir, et toute autre fonctionnant sur des fichiers normaux. Le flux phar supporte toutes les opérations de lecture/écriture à la fois sur les fichiers et sur les répertoires. ]]> La classe Phar implémente des fonctionnalités avancées pour accéder aux fichiers et créer des archives phar. La classe Phar est décrite en détails ici. getFileName() . "\n"; echo file_get_contents($file->getPathName()) . "\n"; // affiche le contenu; } if (isset($p['fichier/interne.php'])) { var_dump($p['fichier/interne.php']->getMetadata()); } // crée un nouveau phar - phar.readonly doit être à 0 dans php.ini // phar.readonly est activé par défaut pour des raisons de sécurité. // Sur des serveurs de production, les Phars n'ont pas besoin d'être créés, // juste d'être exécutés. if (Phar::canWrite()) { $p = new Phar('nouveauphar.tar.phar', 0, 'nouveauphar.tar.phar'); // On crée une archive Phar basée sur tar, compressée par gzip (.tar.gz) $p = $p->convertToExecutable(Phar::TAR, Phar::GZ); // crée une transaction - rien n'est écrit dans nouveauphar.phar // jusqu'à ce que stopBuffering() ne soit appelé, bien qu'un stockage temporaire soit requis $p->startBuffering(); // ajoute tous les fichiers de /chemin/vers/leprojet dans le phar avec le préfixe "projet" $p->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/chemin/vers/leprojet')), '/chemin/vers/'); // ajoute un nouveau fichier en utilisant l'API d'accès par tableau $p['fichier1.txt'] = 'Information'; $fp = fopen('grosfichier.dat', 'rb'); // copie toutes les données du flux $p['data/grosfichier.dat'] = $fp; if (Phar::canCompress(Phar::GZ)) { $p['data/grosfichier.dat']->compress(Phar::GZ); } $p['images/wow.jpg'] = file_get_contents('images/wow.jpg'); // toute valeur peut être sauvegardée comme métadonnée spécifique au fichier $p['images/wow.jpg']->setMetadata(array('mime-type' => 'image/jpeg')); $p['index.php'] = file_get_contents('index.php'); $p->setMetadata(array('bootstrap' => 'index.php')); // sauvegarde l'archive phar sur le disque $p->stopBuffering(); } } catch (Exception $e) { echo 'N\'a pas pu ouvrir le Phar: ', $e; } ?> ]]> D'autre part, la vérification du contenu du fichier phar peut être faite en utilisant un des algorithme de signature symétrique (MD5, SHA1, SHA256 et SHA512 si ext/hash est activée) et en utilisant la signature asymétrique par clé publique/privée de OpenSSL. Pour tirer parti de la signature OpenSSL, vous devez générer une paire de clés publique/privée et utiliser la clé privée pour signer avec Phar::setSignatureAlgorithm. En plus, la clé publique, extraite en utilisant ce code : ]]> doit être sauvegardée à part de l'archive phar qu'elle vérifie. Si l'archive phar est sauvegardée en tant que /chemin/vers/mon.phar, la clé publique doit être sauvegardée en tant que /chemin/vers/mon.phar.pubkey, sans quoi phar ne sera pas capable de vérifier la signature OpenSSL. La classe Phar fournit aussi trois méthodes statiques, Phar::webPhar, Phar::mungServer et Phar::interceptFileFuncs qui sont cruciales pour empaqueter des applications PHP visant à être utilisée sur un système de fichiers classique ou en tant qu'application web. Phar::webPhar implémente un contrôleur qui route les appels HTTP vers le bon endroit de l'archive phar. Phar::mungServer est utilisé pour modifier les valeurs du tableau $_SERVER pour dire aux applications d'utiliser ces valeurs. Phar::interceptFileFuncs dit à Phar d'intercepter les appels à fopen, file_get_contents, opendir, et à toutes les fonctions basées sur stat (file_exists, is_readable, etc) et route tous les chemins relatif vers les bons endroits de l'archive phar. Par exemple, empaqueter une version de la célèbre application phpMyAdmin dans une archive phar nécessite juste ce simple script et, dès lors, phpMyAdmin.phar.tar.php peut être accédé comme un fichier classique à partir de votre serveur web, après avoir modifié le couple utilisateur/motdepasse : startBuffering(); $a["phpMyAdmin-2.11.3-english/config.inc.php"] = 'setStub('stopBuffering(); ?> ]]>
Utiliser les archives Phar : le flux phar Le flux Phar supporte totalement fopen pour les lectures/écritures (pas les concaténations), unlink, stat, fstat, fseek, rename, et les opérations de flux sur les répertoires opendir, et rmdir et mkdir. La compression et les métadonnées individuelles par fichier peuvent aussi être manipulées au sein de l'archive Phar en utilisant les contextes de flux : array('compress' => Phar::GZ)), array('metadata' => array('user' => 'cellog'))); file_put_contents('phar://mon.phar/unfichier.php', 0, $context); ?> ]]> Le flux phar n'agit pas sur les fichiers distants et ne peut pas considérer les fichiers distants, etc... même si les options INI allow_url_fopen et allow_url_include sont désactivées. Bien qu'il soit possible de créer des archives phar de zéro en utilisant juste les opérations sur les flux, il est préférable d'utiliser la fonctionnalité incluse dans la classe Phar. Le flux est mieux utilisé pour les opérations de lecture.
Utiliser les archives Phar : les classes Phar et PharData La classe Phar supporte la lecture et la manipulation des archives Phar, ainsi que l'itération à travers la fonctionnalité héritée de la classe RecursiveDirectoryIterator. Avec le support de l'interface ArrayAccess, les fichiers contenus dans une archive Phar peuvent être accédés comme s'ils étaient membres d'un tableau associatif. La classe PharData étend la classe Phar, et permet la création et la modification d'archives tar et zip non exécutables (données) même si phar.readonly=1 dans php.ini. Ainsi, PharData::setAlias et PharData::setStub sont toutes deux désactivées car les concepts d'alias et de conteneur sont restreints aux archives phar exécutables. Il est important de noter que quand une archive Phar est créée, le chemin complet doit être passé au constructeur de l'objet Phar. Un chemin relatif empêcherait l'initialisation. En supposant que $p est un objet initialisé de cette façon : ]]> Une archive Phar vide sera créée en tant que /chemin/vers/monphar.phar, ou si /chemin/vers/monphar.phar existe déjà, il sera ouvert de nouveau. Le terme monphar.phar démontre le concept d'un alias qui peut être utilisé pour référencer /chemin/vers/monphar.phar dans des URL comme ceci : ]]> Avec l'objet Phar $p nouvellement créé, les choses suivantes sont possibles : $a = $p['fichier.php'] crée une PharFileInfo qui réfère au contenu de phar://monphar.phar/fichier.php $p['fichier.php'] = $v crée un nouveau fichier (phar://monphar.phar/fichier.php), ou écrase un fichier existant au sein de monphar.phar. $v peut être soit une chaîne ou un pointeur vers un fichier ouvert, dans quel cas le contenu du fichier sera utilisé pour créer le nouveau fichier. Notez que $p->addFromString('fichier.php', $v) est équivalent en terme de fonctionnalité au cas ci-dessus. Il est aussi possible d'ajouter le contenu d'un fichier avec $p->addFile('/chemin/vers/fichier.php', 'fichier.php'). Enfin, un répertoire vide peut être créé avec $p->addEmptyDir('vide'). isset($p['fichier.php']) peut être utilisé pour déterminer si phar://monphar.phar/fichier.php existe au sein de monphar.phar. unset($p['fichier.php']) efface phar://monphar.phar/fichier.php de monphar.phar. De plus, l'objet Phar est le seul moyen d'accéder aux métadonnées spécifiques de Phar, via Phar::getMetadata, et c'est aussi le seul moyen de régler ou de récupérer le conteneur du chargeur de l'archive Phar via Phar::getStub et Phar::setStub. De plus, la compression pour l'archive Phar entière peut être manipulée seulement via la classe Phar. La liste complète des fonctionnalités de l'objet Phar est documentée ci-dessous. La classe PharFileInfo étend la classe SplFileInfo et ajoute plusieurs méthodes pour manipuler les métadonnées spécifiques à Phar d'un fichier contenu dans un Phar, telles que manipuler la compression ou les métadonnées.