Phar

Introducción

La extensión phar proporciona un medio para empaquetar una aplicación PHP completa en un único archivo llamado "phar" (PHP Archive) para facilitar la instalación y configuración. Además de este servicio, la extensión también proporciona una clase de abstracción de formato de archivo para crear y manipular archivos tar y zip a través de la clase PharData, de manera similar a como PDO proporciona una interfaz unificada para acceder a diferentes bases de datos. Sin embargo, a diferencia de PDO, que no puede transferir datos entre bases de datos, Phar tiene la capacidad de convertir archivos tar, zip y phar con una sola línea de código. Consulte Phar::convertToExecutable() para obtener un ejemplo.

¿Qué es phar? Las archivos phar son en realidad un medio práctico para agrupar varios archivos en uno solo. Así, un archivo phar permite distribuir una aplicación PHP completa en un único archivo y ejecutarla desde este archivo sin necesidad de extraerlo en el disco. Además, los archivos phar pueden ser ejecutados por PHP tan fácilmente como cualquier otro archivo, tanto desde la línea de comandos como a través de un servidor web. Phar es una especie de memoria USB para aplicaciones PHP.

Phar implementa esta funcionalidad mediante un flujo. Normalmente, para utilizar un archivo externo desde un script PHP, se debe utilizar la función include:

Ejemplo #1 Utilizar un archivo externo

<?php
include '/ruta/al/archivo/externo.php';
?>

Puede considerarse que PHP convierte en realidad /ruta/al/archivo/externo.php en un flujo file:///ruta/al/archivo/externo.php, y que utiliza de forma oculta las funciones de flujo de archivos planos para acceder a archivos locales.

Para utilizar un archivo llamado archivo.php contenido en un archivo phar /ruta/al/miphar.phar, la sintaxis es casi similar a la sintaxis file:// anterior.

Ejemplo #2 Utilizar un archivo contenido en un archivo phar

<?php
include 'phar:///ruta/al/miphar.phar/archivo.php';
?>

En realidad, un archivo phar puede tratarse como si fuera un disco externo, utilizando cualquiera de las funciones relacionadas con fopen(), opendir() y mkdir() para leer, modificar o crear nuevos archivos o directorios dentro del archivo phar. Esto permite que aplicaciones PHP completas sean distribuidas en un único archivo y ejecutadas desde él.

El uso más común de un archivo phar es distribuir una aplicación completa en un único archivo. Por ejemplo, el instalador PEAR que se incluye con las versiones de PHP se distribuye mediante un archivo phar. Para utilizar el archivo phar distribuido de esta manera, este puede ser ejecutado mediante la línea de comandos o a través de un navegador web.

Los archivos phar pueden distribuirse en formato tar, zip o en el formato phar especialmente diseñado para la extensión phar. Cada formato de archivo tiene sus ventajas e inconvenientes. Los archivos zip y tar pueden ser extraídos por cualquier herramienta de terceros que pueda leer el formato, pero requieren la extensión phar para ser ejecutados por PHP. El formato de archivo phar es único y dedicado a la extensión phar y solo puede ser creado por esta o por el paquete PEAR » PHP_Archive, pero tiene la ventaja de no requerir la instalación de la extensión phar para que la aplicación empaquetada pueda ser ejecutada.

En otras palabras, incluso con la extensión phar desactivada, es posible ejecutar o incluir un archivo basado en phar. Acceder a archivos individuales dentro de un archivo phar solo es posible con la extensión phar a menos que el archivo phar haya sido creado por PHP_Archive.

La extensión phar también es capaz de convertir un archivo phar desde un tar hacia un archivo zip o phar con un solo comando:

Ejemplo #3 Convertir un archivo phar al formato tar

<?php
$phar
= new Phar('miphar.phar');
$pgz = $phar->convertToExecutable(Phar::TAR, Phar::GZ); // produce miphar.phar.tar.gz
?>

Phar puede comprimir archivos individuales o un archivo completo utilizando la compresión gzip o bzip2, y puede verificar la integridad del archivo automáticamente utilizando funciones de firma MD5, SHA-1, SHA-256 o SHA-512.

Finalmente, la extensión phar está orientada a la seguridad, desactiva por defecto los accesos de escritura en archivos phar ejecutables y requiere la desactivación a nivel de sistema del parámetro phar.readonly del php.ini para crear o modificar archivos phar. Los archivos tar y zip sin el marcador ejecutable pueden ser siempre creados o modificados utilizando la clase PharData.

Si se crean aplicaciones con el propósito de distribuirlas, se debe leer Cómo crear archivos Phar. Si se desea más información sobre las diferencias entre los formatos de archivo que phar soporta, se debe leer Phar, Tar y Zip.

Si se utilizan aplicaciones phar, hay trucos muy útiles en Cómo utilizar archivos Phar.

La palabra phar es la contracción de PHP y de Archive y está fuertemente inspirada en la palabra jar (Java Archive) familiar a los desarrolladores Java.

La implementación de los archivos Phar se basa en el paquete PEAR » PHP_Archive, y los detalles de implementación son los mismos, aunque la extensión Phar es más potente. Además, esta permite que la mayoría de las aplicaciones PHP sean ejecutadas sin modificación mientras que los archivos basados en PHP_Archive requieren a menudo muchas modificaciones para funcionar.

add a note

User Contributed Notes 6 notes

up
35
dava
12 years ago
Here is an apache2 htaccess example that prevents the downloading of phar-Archives by the user:

RewriteEngine on
RewriteRule ^(.*)\.phar$ - [F]

It triggers a "403 - Forbidden" message instead of delivering the archive.
up
17
bohwaz
14 years ago
If you get blank pages when trying to access a phar web-page, then you probably have Suhosin on your PHP (like in Debian and Ubuntu), and you need to ad this to your php.ini to allow execution of PHAR archives :

suhosin.executor.include.whitelist="phar"
up
6
v-mafick at microsoft dot com
12 years ago
Users should set the `sys_temp_dir` directive.

PHAR stores temporary files in either `sys_temp_dir` or the current working directory(CWD).

This is especially important if you're CWD is on a remote file system. Often web server clusters will share a common file system between each web server (using NFS, DFS, etc...). In such scenarios, if you don't set `sys_temp_dir` to a local directory, PHAR will be creating temporary files over the network, which will result in performance and functionality problems.
up
3
brunoczim
8 years ago
Here is a very simple program for creating phar files with CLI. Note that it requires phar.readonly in php.ini  set to false (Off).

<?php
$filename = "default";
$dir = "./";
$regex = "/^(?!.*build\\.php)(?:.*)$/";
$main = "main.php";
$shebang = "#!/usr/bin/env php";
$chmod = true;

for ($i = 0; $i < $argc; $i++) {
    switch ($argv[$i]) {
        case "-o":
            $i++;
            if ($i >= $argc) {
                echo "Missing output file name" . PHP_EOL;
                exit(1);
            }
            $filename = $argv[$i];
            break;
        case "-i":
            $i++;
            if ($i >= $argc) {
                echo "Missing input directory name" . PHP_EOL;
                exit(1);
            }
            $dir = $argv[$i];
            break;
        case "-p":
            $i++;
            if ($i >= $argc) {
                echo "Missing regular expression pattern" . PHP_EOL;
                exit(1);
            }
            $regex = $argv[$i];
            break;
        case "-m":
            $i++;
            if ($i >= $argc) {
                echo "Missing main file" . PHP_EOL;
                exit(1);
            }
            $main = $argv[$i];
            break;
        case "-b":
            $i++;
            if ($i >= $argc) {
                echo "Missing shebang of file" . PHP_EOL;
                exit(1);
            }
            $shebang = $argv[$i];
            break;
        case "--no-chmod":
            $chmod = false;
            break;
    }
}
if (file_exists($filename)) unlink($filename);
$phar = new Phar($filename);
$phar->buildFromDirectory($dir, $regex);
$phar->setStub(($shebang ? $shebang . PHP_EOL : "") . $phar->createDefaultStub($main));
if ($chmod) {
    chmod($filename, fileperms($phar) | 0700);
}
up
1
lemonkid from OpenToAll
7 years ago
when read via phar://, stream will unserialize object including phar file

Use this to create phar
<?php
// create new Phar
$phar = new Phar('lemon.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ? >');

// add object of any class as meta data
class AnyClass {}
$object = new AnyClass;
$object->data = 'Chanh';
$phar->setMetadata($object);
$phar->stopBuffering();
?>

and read it by:
<?php
class AnyClass {
    function __destruct() {
        echo $this->data;
    }
}
// output: Chanh
file_get_contents('phar://test.phar');
?>
up
1
t dot habenreich at web dot de
12 years ago
Here is a very simple class to build a phar file from a given source directory. You can use this for your own project and simple deployment.

But my main goal was to show how to use PHAR functions in a simple way.

<?php

class BuildPhar
{
  private $_sourceDirectory = null;
  private $_stubFile        = null;
  private $_outputDirectory = null;
  private $_pharFileName    = null;

  /**
   * @param $_sourceDirectory       // This is the directory where your project is stored.
   * @param $stubFile               // Name the entry point for your phar file. This file have to be within the source
   *                                   directory. 
   * @param null $_outputDirectory  // Directory where the phar file will be placed.
   * @param string $pharFileName    // Name of your final *.phar file.
   */
  public function __construct($_sourceDirectory, $stubFile, $_outputDirectory = null, $pharFileName = 'myPhar.phar') {

    if ((file_exists($_sourceDirectory) === false) || (is_dir($_sourceDirectory) === false)) {
      throw new Exception('No valid source directory given.');
    }
    $this->_sourceDirectory = $_sourceDirectory;

    if (file_exists($this->_sourceDirectory.'/'.$stubFile) === false) {
      throw new Exception('Your given stub file doesn\'t exists.');
    }

    $this->_stubFile = $stubFile;

    if(empty($pharFileName) === true) {
      throw new Exception('Your given output name for your phar-file is empty.');
    }
    $this->_pharFileName = $pharFileName;

    if ((empty($_outputDirectory) === true) || (file_exists($_outputDirectory) === false) || (is_dir($_outputDirectory) === false)) {

      if ($_outputDirectory !== null) {
        trigger_error ( 'Your output directory is invalid. We set the fallback to: "'.dirname(__FILE__).'".', E_USER_WARNING);
      }

      $this->_outputDirectory = dirname(__FILE__);
    } else {
      $this->_outputDirectory = $_outputDirectory;
    }

    $this->prepareBuildDirectory();
    $this->buildPhar();
  }

  private function prepareBuildDirectory() {
    if (preg_match('/.phar$/', $this->_pharFileName) == FALSE) {
      $this->_pharFileName .= '.phar';
    }

    if (file_exists($this->_pharFileName) === true) {
      unlink($this->_pharFileName);
    }
  }

  private function buildPhar() {
    $phar = new Phar($this->_outputDirectory.'/'.$this->_pharFileName);
    $phar->buildFromDirectory($this->_sourceDirectory);
    $phar->setDefaultStub($this->_stubFile);
  }
}
//END Class

//Example Usage:
$builder = new BuildPhar(
  dirname(__FILE__).'/_source',
  'my_default_stub.php',
  dirname(__FILE__).'/_output',
  'my-phar-file.phar'
);
To Top