Utiliser Phar pour packager un projet

De e-glop
Révision datée du 14 janvier 2016 à 15:38 par BeTa (discussion | contributions) (e-venement ou un autre projet Symfony1)

Construire son archive Phar

Script de construction

Créer un make-archive.php comme suit :

<?php
 $path = $_SERVER['argv'][2].'e-venement.phar.php';
 if ( file_exists($path) )
   unlink($path);
 $phar = new Phar($path, NULL, 'e-venement.phar.php');
 
 $phar->buildFromDirectory($_SERVER['argv'][1]);
 $phar->setStub("<?php
   Phar::mapPhar('e-venement.phar.php');
   
   Phar::webPhar();
   Phar::mungServer();
   Phar::interceptFileFuncs();
   
   __HALT_COMPILER();
 ?>");
 
 $phar->stopBuffering();


Et appelez-le via la commande :

 $ php -d phar.readonly=0 make-archive.php [RÉPERTOIRE À PACKAGER]

Si vous avez des répertoires où vous aurez à écrire des données

Utiliser la commande :

 Phar::mount('/writable/path/cache/', 'phar://e-venement.phar.php/cache/');

Ainsi, toutes les écritures dans ./cache (dans l'archive) seront envoyées dans /writable/path/cache/ (équivalent d'un mount UNIX).

Placez cette commande (au choix) :

  • dans un fichier chargé en début d'exécution de votre application
  • dans un fichier que vous aurez créé spécialement et qui sera chargé avant (ou au tout début de) chaque exécution de votre application
  • dans un stub de votre archive Phar

Les commandes à oublier / remplacer

realpath()

À remplacer par la fonction suivante :

 function realpath2($path)
 {
   // whether $path is unix or not
   $unipath = strlen($path)==0 || $path{0}!='/';
   $unc = substr($path,0,2)=='\\\\'?true:false;
   // attempts to detect if path is relative in which case, add cwd
   if(strpos($path,':') === false && $unipath && !$unc){
       $path=getcwd().DIRECTORY_SEPARATOR.$path;
       if($path{0}=='/'){
           $unipath = false;
       }
   }
   
   // resolve path parts (single dot, double dot and double delimiters)
   $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
   $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
   $absolutes = array();
   foreach ($parts as $part) {
       if ('.'  == $part){
           continue;
       }
       if ('..' == $part) {
           array_pop($absolutes);
       } else {
           $absolutes[] = $part;
       }
   }
   $path = implode(DIRECTORY_SEPARATOR, $absolutes);
   // resolve any symlinks
   if( function_exists('readlink') && file_exists($path) && linkinfo($path)>0 ){
       $path = readlink($path);
   }
   // put initial separator that could have been lost
   $path = !$unipath ? '/'.$path : $path;
   $path = $unc ? '\\\\'.$path : $path;
   
   // TODO
   $path = str_replace('phar:', 'phar://', $path);
   return $path;
 }

getcwd()

Utiliser la constante __DIR__ à la place.

e-venement ou un autre projet Symfony1

Se dotter d'un script make-archive.php adapté

Symfony1 requiert la possibilité de lancer des tâches depuis la ligne de commande "CLI". Il faut donc se permettre de lancer ces commandes depuis l'extérieur de la Phar.

Rajoutez donc ces éléments dans votre fichier make-archive.php :

   // ...
   Phar::mapPhar('e-venement.phar.php');
   
   if ( isset(\$_SERVER['argv']) )
   if ( \$_SERVER['argv'][1] == './symfony' )
   {
     \$php = 'phar://e-venement.phar.php/'.\$_SERVER['argv'][1];
     
     foreach ( \$_SERVER['argv'] as \$i => \$arg )
     if ( \$i > 1 )
       \$_SERVER['argv'][\$i-1] = \$arg;
     array_pop(\$_SERVER['argv']);
     
     require \$php;
     die();
   }
   
   Phar::webPhar();
   // ...

Se créer une instance initiale

Prendre un déploiement fonctionnel d'e-venement (fichiers de configuration inclus) et le recopier ainsi :

 $ cp -Lr [REPSOURCE] [REPDESTINATION]

Cela élimine tous les problèmes liés aux liens symboliques...

Les problèmes de path

1. Remplacer tous les appels à realpath() par realpath2() 2. Remplacer tous les appels à getcwd() par __DIR__ 3. Retirer la première ligne du fichier ./symfony (#!/usr/bin/php)

Répertoires cache et log

Rajouter un paramétrage particulier pour les répertoires de cache, de log, etc... dans votre fichier config/ProjectConfiguration.php :

 public function setup()
 {
   $this->setCacheDir('/tmp/myproject/cache');
   $this->setLogDir('/tmp/myproject/log');
   // ...
 }