Javascript debugger
Website design
↑
The phar extension
provides the phar
stream wrapper and the Phar
class for manipulating self-contained PHP Archive (phar) files. The
Phar class can be used to create and to extract contents of phar files as
well as iterating over their contents.
PHP Archive files (Phars) are special collections of files that can be transparently run right out of the file, similar to Java's jar archive files. Using a phar archive, it is possible to distribute a complete PHP application in a single file that will run out of the file without modification or extraction. Phar archives can also be used to store files for extraction similar to tar or zip archive files. Phars support compression using gzip if the zlib extension is present, and using bzip2 if the bz2 extension is present. In addition, iteration and other features are available if the SPL extension is available. Phar signature verification using md5 or sha1 is natively supported to ensure archive integrity.
The original implementation for Phar archives was in the PEAR package
» PHP_Archive, and
the implementation details are very similar, although the Phar extension
is more full-featured. PHP_Archive has more flexibility in Phar creation,
and helpful debugging tools like the PHP_Archive_Manager
class, and the Phar extension supports iteration, array access, and
directly manipulating Phar contents through a simple interface. PHP_Archive
supports creation of Phar archives that can be processed using the Phar
extension or PHP_Archive seamlessly, whereas the Phar extension is designed
to create extensions that function with the Phar extension. In addition,
the Phar extension will continue to work even if the
allow_url_include or
allow_url_fopen INI variables
are disabled, while PHP_Archive-based Phar archives (without the Phar extension)
will not function.
Phar requires PHP 5.2.0 or newer. Additional features require the
SPL extension in order to take advantage
of iteration and array access to a Phar's file contents. The phar
stream does not require any additional extensions to function.
You may optionally wish to enable the zlib and bzip2 extensions to take advantage of compressed phar support.
Windows binaries may be found at
» http://snaps.php.net/.
To install, download php_phar.dll to the folder specified
by your php.ini file's extension_dir
directive.
Enable it by adding extension=php_phar.dll
to your php.ini and restarting your web server.
extension_dir=c:/php5/exts/
extension=php_phar.dll
Linux, BSD, and other *nix variants can be compiled using the following steps:
Either:
pecl install phar
phar.so
from the directory indicated by the
build process to the location specified in your php.ini file under
extension_dir
.
extension=phar.so
to your php.ini
Or:
Set the path to your php.ini via:
pecl config-set php_ini /path/to/php.ini
pecl install phar
There are currently no stable
versions of PECL/phar,
to force installation of the alpha
version of PECL/phar
execute: pecl install phar-
alpha
Rather than using pecl install phar
to automatically
download and install PECL/phar, you may download the tarball from
» PECL.
From the root of the unpacked tarball, run:
phpize && ./configure --enable-phar && make
to generate phar.so
.
Once built, continue the installation from step 4 above.
Information for installing this PECL extension may be found in the manual chapter titled Installation of PECL extensions. Additional information such as new releases, downloads, source files, maintainer information, and a CHANGELOG, can be located here: » http://pecl.php.net/package/phar.
The behaviour of these functions is affected by settings in php.ini
.
Name | Default | Changeable | Changelog |
---|---|---|---|
phar.readonly | "1" | PHP_INI_ALL | |
phar.require_hash | "1" | PHP_INI_ALL | |
phar.extract_list | "" | PHP_INI_ALL | Available since phar 1.1.0. |
Here's a short explanation of the configuration directives.
This option disables creation or modification of Phar archives
using the phar
stream or Phar
object's write support. This setting should always be enabled on
production machines, as the phar extension's convenient write support
could allow straightforward creation of a php-based virus when coupled
with other common security vulnerabilities.
This setting can only be unset in php.ini due to security reasons.
If phar.readonly
is disabled in php.ini, the
user may enable phar.readonly
in a script
or disable it later. If phar.readonly
is
enabled in php.ini, a script may harmlessly "re-enable"
the INI variable, but may not disable it.
This option will force all opened Phar archives to contain some kind of signature (currently MD5 and SHA1 are supported), and will refuse to process any Phar archive that does not contain a signature.
This setting can only be unset in php.ini due to security reasons.
If phar.require_hash
is disabled in php.ini, the
user may enable phar.require_hash
in a script
or disable it later. If phar.require_hash
is
enabled in php.ini, a script may harmlessly "re-enable"
the INI variable, but may not disable it.
Allows mappings from a full path to a phar archive or its alias to
the location of its extracted files.
The format of the parameter is name=archive,name2=archive2
.
This allows extraction of phar files to disk, and allows phar to act as a
kind of mapper to extracted disk files. This is often done for performance
reasons, or to assist with debugging a phar.
in php.ini:
phar.extract_list = archive=/full/path/to/archive/,arch2=/full/path/to/arch2
<?php
include "phar://archive/content.php";
include "phar://arch2/foo.php";
?>
The Phar extension provides the phar
stream, which
allows accessing files contained within a phar transparently. The
file format of a Phar is described here
Phar archives are similar in concept to Java JAR archives, but are tailored to the needs and to the flexibility of PHP applications. A Phar archive is used to distribute a complete PHP application or library in a single file. Unlike Java's implementation of JAR archives, no external tool is required to process or run a PHP Phar archive. A Phar archive application is processed exactly like any other PHP application:
php coolapplication.phar
Using a Phar archive library is identical to using any other PHP library:
<?php
include 'coollibrary.phar';
?>
What makes Phar archives incredibly useful is the phar
stream wrapper, which is explained in depth here.
Using this stream wrapper, it is possible to access
individual files within a phar as if the phar were its own filesystem.
The phar
stream wrapper supports all read/write operations
on files, and opendir() on directories.
<?php
include 'phar://coollibrary.phar/internal/file.php';
header('Content-type: image/jpeg');
// phars can be accessed by full path or by alias
echo file_get_contents('phar:///fullpath/to/coollibrary.phar/images/wow.jpg');
?>
Also provided with the Phar extension is the Phar
class,
which allows accessing the files of the Phar archive as if it were an
associative array, and other functionality. The Phar class is explained
here.
<?php
try {
// open an existing phar
$p = new Phar('coollibrary.phar');
foreach ($p as $file) {
// $file is a PharFileInfo class, and inherits from SplFileInfo
echo $file->getFileName() . "\n";
echo $file . "\n"; // display contents;
}
if (isset($p['internal/file.php'])) {
var_dump($p['internal/file.php']->getMetaData());
}
// create a new phar - phar.readonly must be 0 in php.ini
// phar.readonly is enabled by default for security reasons.
// On production servers, Phars need never be created,
// only executed.
if (Phar::canWrite()) {
$p = new Phar(dirname(__FILE__) . '/newphar.phar', 0, 'newphar.phar');
// create transaction - nothing is written to newphar.phar
// until commit() is called, although temporary storage is needed
$p->begin();
// add a new file, set its contents
$p['file1.txt'] = 'Information';
$fp = fopen('hugefile.dat', 'rb');
// copy from the stream
$p['data/hugefile.dat'] = $fp;
if (Phar::canCompress()) {
$p['data/hugefile.dat']->setCompressedGZ();
}
$p['images/wow.jpg'] = file_get_contents('images/wow.jpg');
// any value can be saved as file-specific meta-data
$p['images/wow.jpg']->setMetaData(array('mime-type' => 'image/jpeg'));
$p['index.php'] = file_get_contents('index.php');
$p->setMetaData(array('bootstrap' => 'index.php'));
// set the loader stub
$p->setStub('<?php
$p = new Phar(__FILE__);
$m = $p->getMetaData();
require "phar://" . __FILE__ . "/" . $m["bootstrap"];
__HALT_COMPILER();');
// save the phar archive to disk
$p->commit();
}
} catch (Exception $e) {
echo 'Could not open Phar: ', $e;
}
?>
The Phar stream wrapper fully supports fopen() for read, write or append, unlink(), stat(), fstat(), fseek(), rename() and directory stream operation opendir(). The Phar stream wrapper does not support creating or erasing a directory, as files are stored only as files, and the concept of an abstract directory does not exist.
Individual file compression and per-file metadata can also be manipulated in a Phar archive using stream contexts:
<?php
$context = stream_context_create(array('phar' =>
array('compression' => Phar::GZ)),
array('metadata' => array('user' => 'cellog')));
file_put_contents('phar://my.phar/somefile.php', 0, $context);
?>
The phar
stream wrapper does not operate on remote files,
and cannot operate on remote files, and so is allowed even when the
allow_url_fopen and
allow_url_include INI options
are disabled.
Although it is possible to create phar archives from scratch just using stream operations, it is best to use the functionality built into the Phar class. The stream wrapper is best used for read operations.
The Phar
class supports reading and manipulation
of Phar archives, as well as iteration through inherited functionality of
the
» RecursiveDirectoryIterator
class. With support for the ArrayAccess
interface, files inside a Phar archive can be accessed as if they were
part of an associative array.
It is important to note that when creating a Phar archive, the full path
should be passed to the Phar
object constructor.
Relative paths will fail to initialize.
Assuming that $p
is a Phar object initialized as follows:
<?php
$p = new Phar('/path/to/myphar.phar', 0, 'myphar.phar');
?>
An empty Phar archive will be created at /path/to/myphar.phar
,
or if /path/to/myphar.phar
already exists, it will be opened
again. The literal myphar.phar
deomnstrates the concept of an alias
that can be used to reference /path/to/myphar.phar
in URLs as in:
<?php
// these two calls to file_get_contents() are equivalent if
// /path/to/myphar.phar has an explicit alias of "myphar.phar"
// in its manifest, or if the phar was initialized with the
// previous example's Phar object setup
$f = file_get_contents('phar:///path/to/myphar.phar/whatever.txt');
$f = file_get_contents('phar://myphar.phar/whatever.txt');
?>
With the newly created $p
Phar
object,
the following is possible:
$a = $p['file.php']
creates a PharFileInfo
class that refers to the contents of phar://myphar.phar/file.php
$p['file.php'] = $v
creates a new file
(phar://myphar.phar/file.php
), or overwrites
an existing file within myphar.phar
. $v
can be either a string or an open file pointer, in which case the entire
contents of the file will be used to create the new file.
isset($p['file.php'])
can be used to determine
whether phar://myphar.phar/file.php
exists within
myphar.phar
.
unset($p['file.php'])
erases
phar://myphar.phar/file.php
from
myphar.phar
.
In addition, the Phar
object is the only way to access
Phar-specific metadata, through
Phar->getMetaData(),
and the only way to set or retrieve a Phar archive's PHP loader stub through
Phar->getStub() and
Phar->setStub().
Additionally, compression for the entire Phar archive at once can only be manipulated
using the Phar
class.
The full list of Phar
object functionality is documented
below.
The PharFileInfo
class extends the
» SplFileInfo
class, and adds several methods for manipulating Phar-specific details of a file
contained within a Phar, such as manipulating compression and metadata.
All Phar files contain three to four sections:
a stub
a manifest describing the contents
the file contents
[optional] a signature for verifying Phar integrity
A Phar's stub is a simple PHP file. The smallest possible stub follows:
<?php __HALT_COMPILER();
A stub must contain as a minimum, the __HALT_COMPILER();
token
at its conclusion. Typically, a stub will contain loader functionality
like so:
<?php
Phar::mapPhar();
include 'phar://myphar.phar/index.php';
__HALT_COMPILER();
There are no restrictions on the contents of a Phar stub, except for the requirement
that it conclude with __HALT_COMPILER();
. The closing PHP tag
?>
may be included or omitted, but there can be
no more than 1 space between the ;
and the close tag
?>
or the phar extension will be unable
to process the Phar archive's manifest.
The Phar manifest is a highly optimized format that allows per-file specification of file compression, file permissions, and even user-defined meta-data such as file user or group. All values greater than 1 byte are stored in little-endian byte order, with the exception of the API version, which for historical reasons is stored as 3 nibbles in big-endian order.
All unused flags are reserved for future use, and must not be used to store custom information. Use the per-file meta-data facility to store customized information about particular files.
The basic file format of a Phar archive manifest is as follows:
Size in bytes | Description |
---|---|
4 bytes | Length of manifest in bytes (1 MB limit) |
4 bytes | Number of files in the Phar |
2 bytes | API version of the Phar manifest (currently 1.0.0) |
4 bytes | Global Phar bitmapped flags |
4 bytes | Length of Phar alias |
?? | Phar alias (length based on previous) |
4 bytes | Length of Phar metadata (0 for none) |
?? | Serialized Phar Meta-data, stored in serialize() format |
at least 24 * number of entries bytes | entries for each file |
Here are the bitmapped flags currently recognized by the Phar extension for the global Phar flat bitmap:
Value | Description |
---|---|
0x00010000 | If set, this Phar contains a verification signature |
0x00001000 | If set, this Phar contains at least 1 file that is compressed with zlib compression |
0x00002000 | If set, this Phar contains at least 1 file that is compressed with bzip compression |
Each file in the manifest contains the following information:
Size in bytes | Description |
---|---|
4 bytes | Filename length in bytes |
?? | Filename (length specified in previous) |
4 bytes | Un-compressed file size in bytes |
4 bytes | Unix timestamp of file |
4 bytes | Compressed file size in bytes |
4 bytes | CRC32 checksum of un-compressed file contents |
4 bytes | Bit-mapped File-specific flags |
4 bytes | Serialized File Meta-data length (0 for none) |
?? | Serialized File Meta-data, stored in serialize() format |
The File-specific bitmap values recognized are:
Value | Description |
---|---|
0x000001FF | These bits are reserved for defining specific file permissions of a file. Permissions are used for fstat() and can be used to recreate desired permissions upon extraction. |
0x00001000 | If set, this file is compressed with zlib compression |
0x00002000 | If set, this file is compressed with bzip compression |
Phars containing a signature always have the signature appended to the end of the Phar archive after the loader, manifest, and file contents. The two signature formats supported at this time are MD5 and SHA1.
Length in bytes | Description |
---|---|
16 or 20 bytes | The actual signature, 20 bytes for an SHA1 signature, 16 bytes for an MD5 signature. |
4 bytes |
Signature flags. 0x0001 is used to
define an MD5 signature, and 0x0002 is used
to define an SHA1 signature.
|
4 bytes |
Magic GBMB used to define the presence of a signature.
|
Table of Contents