Utiliser les archives PharUtiliser 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.