L'extension PHAR permet de mettre plusieurs fichiers php d'un seul fichier et de ne fournir ainsi qu'un seul fichier.
Ayant trouvé la chose intéressant je me suis penché dessus ....
L'extension PHAR (pour « PHP Archive ») est native à partir de la version 5.3 de php (en PECL avant).
imaginons que nous ayons une "application" que l'on souhaite distribuer facilement et que son exploitation soit simple. Il est plus facile de fournir un fichier qu'une dizaine. Lors d'une mise à jour, plutôt que la faire au coup par coup on à un seul fichier à modifier.
Pour résumer :
Tous se passe autour de la classe Phar, celle ci permet la création et la modification des archive Phar a partir d'un fichier php.
Exemple de base :
<?php // création de l’objet phar et indication du nom de fichier final $phar = new Phar('fichierFinal.phar',0,'fichierFinal.phar'); // ajout d'un fichier dans l'archive phar $phar->addFile('fichier.php'); $phar->stopBuffering(); ?>
/! La classe Phar utilise, comme la plus part (toutes ?) des classes PHP le système d'exception pour la gestion d'erreur. Afin de traiter correctement les éventuelle erreur le code devrait donc être :
<?php try { // création de l’objet phar et indication du nom de fichier final $phar = new Phar('fichierFinal.phar',0,'fichierFinal.phar'); // ajout d'un fichier dans l'archive phar $phar->addFile('fichier.php'); $phar->stopBuffering(); } catch (Exception $e){ echo $e->getmessage(); // A vous de voir comment traiter l'erreur ;) } ?>
Je suis obligé de mettre une ligne par fichier que je veut dans le fichier ?
Non non, il existe une méthode permettant d'inclure directement un répertoire buildFromDirectory.
Fiou je suis rassuré la ;)
Vous pouvez pour cela : - Le faire en ligne de commande de la façon suivante : php -d phar.readonly=0 fichierdecreation.php - Directement avec le navigateur si et seulement si la directive phar.readonly est définie à off dans le php.ini (ou que vous le fassiez dans le script).
Cette directive, activée par défaut, empêche toute modification d'une archive phar. Ceci est prévu pour un serveur de production où ce type de comportement ne semble pas utile.
Les archives Phar possède un mécanisme permettant l'appel de code à l'inclusion de celle-ci. Par défaut il s'agit de l'appel au fichier 'index.php' (que celui-ci existe pas dans l'archive !!!).
ce phénomène n'est pas problématique si vous fournissez une appli complète, mais si c'est seulement une "librairie" cela le devient et vous aurez droit au message d'erreur suivant :
il est possible d'accèder à un fichier se trouvant dans une archive avec les fonctions de manipulation de fichier habituelle avec le flux phar://.
Par exemple
<?php $fichier = file_get_content('phar://fichier.phar/fichiercontenu.php'); //et même inclure juste un fichier include 'phar://fichier.phar/fichierContenuInclus.php'; ?>
</pre> <h3>Exemple concret</h3> <p>Dans cet exemple nous allons une application qui gère et affiche les news d'un site. Elle est composée de : - index.php qui affiche les news - news.class.php // gestion des news - commentaireNews.class.php // gestion des commentaire des news le tous est dans le répertoire news donc : /creerphar.php /news/index.php /news/news.class.php /news/commentaireNews.class.php <br /></p> <h4>Création de l'archive</h4> <pre> <?php try { $phar = new Phar(__DIR__ . '/news.phar', Phar::CURRENT_AS_FILEINFO | Phar::KEY_AS_FILENAME, 'news.phar'); $phar->buildFromDirectory(__DIR__ . '/news', '/.php$/'); $phar->stopBuffering(); } catch (Exception $e){ echo 'erreur PHAR : '.$e->getMessage()."rn". $e->getFile(). "rn". $e->getFile() . ."rn". $e->getTraceAsString(); } ?>
Au passage vous voyer l'arrivé de constante dans le constructeur, pour plus d'info la doc. N'ayez pas peur j'ai pas trompé la classe phar est enfant de filesystemeiterator (enfin de RecursiveDirectoryIterator mais qui hérite de filesystemiterator).
<?php include 'news.phar'; ?>
He oui c'est si simple avec un simple include on peut utiliser un système de news complet ;)
Comme je l'indiqué plus haut les archives phar dispose d'un mécanisme de chargement automatique à l'appel du fichier avec ///php ///
Par exemple à appeler directement notre fichier index.php sans que l'on fasse quoi que ce soit ;)
Il est aussi possible de l'utiliser pour appeler un fichier précis autre que l'index afin de réaliser une tache particulière (comme par exemple un autoload etc).
Bien entendu, tous est prévu pour cela avec la méthode setStub qui permet de définir (à partir de code php valide) un chargeur personnalisé. %% Il est a noter que le chargeur doit toujours finir par __HALT_COMPILER(); et que le ?> final n'est pas obligatoire (oui il n'est pas obligatoire pour un code valide, lorsqu'il s'agit du dernier du fichier et qu'il n'y a rien derrière).
par exemple ré-écrivons le chargeur d'origine a titre d'exemple (à partir de l'exemple précédent)
<?php try { $phar = new Phar(__DIR__ . '/news.phar', Phar::CURRENT_AS_FILEINFO | Phar::KEY_AS_FILENAME, 'news.phar'); $phar->buildFromDirectory(__DIR__ . '/news', '/.php$/'); $stub = <<<STUB <?php Phar::mapPhar('news.phar'); require_once('phar://news.phar/autoload.php'); spl_autoload_register('autoload'); __HALT_COMPILER(); STUB; $phar->setStub($stub); //ajoute le chargeur $phar->stopBuffering(); } catch (Exception $e){ echo 'erreur PHAR : '.$e->getMessage()."rn". $e->getFile(). "rn". $e->getFile() . ."rn". $e->getTraceAsString(); } ?>
Le fichier autoload.php
<?php function autoload($classe) { include $classe.'class.php'; } ?>
<?php include 'news.php'; $news = new news(); $commentaire = new commentaireNews(); // etc ?>
Lorsque l'on créer ainsi l'archive phar on prend le contenu du répertoire (à la racine du répertoire) mais l'on ne garde pas l'arborescence donc autoload.php qui, à la base, se trouve dans /news/ va être à la racine dans l'archive d'ou l'appel phar://news.phar/autoload.php. On vois que dans le chargeur on utilise la syntaxe d'ouverture de flux comme si l'on était à l'extérieur de l'archive.
Il est possible d'ajouter des méta data, et ainsi indiquer des informations intéressante comme la version l'auteur, une description etc.
Pour cela nous pouvons utiliser la méthode setMetadata.
Exemple :
<?php try { $phar = new Phar(__DIR__ . '/news.phar', Phar::CURRENT_AS_FILEINFO | Phar::KEY_AS_FILENAME, 'news.phar'); $phar->buildFromDirectory(__DIR__ . '/news', '/.php$/'); 'version' => '412', 'author' => 'Moogli', 'description' => 'Ben ça sert à aafficher des news hein ;)' ) ); $phar->stopBuffering(); } catch (Exception $e){ echo 'erreur PHAR : '.$e->getMessage()."rn". $e->getFile(). "rn". $e->getFile() . ."rn". $e->getTraceAsString(); } ?>
ainsi en ligne de commande vous pouvez utiliser php news.phar -i pour retrouver ces données ou avec la méthode http://fr2.php.net/manual/en/phar.getmetadata.php.
l'exemple de la doc
<?php // crée avec l'alias "projet.phar" $phar = new Phar('projet.phar', 0, 'projet.phar'); $phar->buildFromIterator( new RecursiveIteratorIterator( new RecursiveDirectoryIterator('/chemin/vers/projet')), '/chemin/vers/projet'); $phar->setStub($phar->createDefaultWebStub('cli/index.php', 'www/index.php')); ?>
Avez ça vous pouvez inclures tous ce qu'il y a dans les sous répertoires du chemin par défaut que cela soit du php ou autre.
Les liens qui m'ont permis de découvrir la chose :
Phar : PHP Archive
Phar sur le Blob mageekbox
Surement a compléter !