©
本文档使用 PHP中文网手册 发布
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. A Phar archive application is used 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' ;
?>
The phar stream wrapper provides the core of the phar extension, and is explained in detail here. The phar stream wrapper allows accessing the files within a phar archive using PHP's standard file functions fopen() , opendir() , and others that work on regular files. The phar stream wrapper supports all read/write operations on both files and 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' );
?>
The Phar class implements advanced functionality for accessing files and for creating phar archives. The Phar class is explained in detail here.
<?php
try {
// open an existing phar
$p = new Phar ( 'coollibrary.phar' , 0 );
// Phar extends SPL's DirectoryIterator class
foreach (new RecursiveIteratorIterator ( $p ) as $file ) {
// $file is a PharFileInfo class, and inherits from SplFileInfo
echo $file -> getFileName () . "\n" ;
echo file_get_contents ( $file -> getPathName ()) . "\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 ( 'newphar.tar.phar' , 0 , 'newphar.tar.phar' );
// make this a tar-based phar archive, compressed with gzip compression (.tar.gz)
$p = $p -> convertToExecutable ( Phar :: TAR , Phar :: GZ );
// create transaction - nothing is written to newphar.phar
// until stopBuffering() is called, although temporary storage is needed
$p -> startBuffering ();
// add all files in /path/to/project, saving in the phar with the prefix "project"
$p -> buildFromIterator (new RecursiveIteratorIterator (new DirectoryIterator ( '/path/to/project' )), '/path/to/' );
// add a new file via the array access API
$p [ 'file1.txt' ] = 'Information' ;
$fp = fopen ( 'hugefile.dat' , 'rb' );
// copy all data from the stream
$p [ 'data/hugefile.dat' ] = $fp ;
if ( Phar :: canCompress ( Phar :: GZ )) {
$p [ 'data/hugefile.dat' ]-> compress ( Phar :: GZ );
}
$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' ));
// save the phar archive to disk
$p -> stopBuffering ();
}
} catch ( Exception $e ) {
echo 'Could not open Phar: ' , $e ;
}
?>
In addition, verification of phar file contents can be done using any of the supported symmetric hash algorithms (MD5, SHA1, SHA256 and SHA512 if ext/hash is enabled) and using asymmetric public/private key signing using OpenSSL (new in Phar 2.0.0). To take advantage of OpenSSL signing, you need to generate a public/private key pair, and use the private key to set the signature using Phar::setSignatureAlgorithm() . In addition, the public key as extracted using this code:
<?php
$public = openssl_get_publickey ( file_get_contents ( 'private.pem' ));
$pkey = '' ;
openssl_pkey_export ( $public , $pkey );
?>
As of version 2.0.0, The Phar class also provides 3 static methods, Phar::webPhar() , Phar::mungServer() and Phar::interceptFileFuncs() that are crucial to packaging up PHP applications designed for usage on regular filesystems and for web-based applications. Phar::webPhar() implements a front controller that routes HTTP calls to the correct location within the phar archive. Phar::mungServer() is used to modify the values of the $_SERVER array to trick applications that process these values. Phar::interceptFileFuncs() instructs Phar to intercept calls to fopen() , file_get_contents() , opendir() , and all of the stat-based functions ( file_exists() , is_readable() and so on) and route all relative paths to locations within the phar archive.
As an example, packaging up a release of the popular phpMyAdmin application for use as a phar archive requires only this simple script and then phpMyAdmin.phar.tar.php can be accessed as a regular file from your web server after modifying the user/password:
<?php
@ unlink ( 'phpMyAdmin.phar.tar.php' );
copy ( 'phpMyAdmin-2.11.3-english.tar.gz' , 'phpMyAdmin.phar.tar.php' );
$a = new Phar ( 'phpMyAdmin.phar.tar.php' );
$a -> startBuffering ();
$a [ "phpMyAdmin-2.11.3-english/config.inc.php" ] = '<?php
$i = 0;
$i++;
$cfg[\'Servers\'][$i][\'host\'] = \'localhost\';
$cfg[\'Servers\'][$i][\'extension\'] = \'mysqli\';
$cfg[\'Servers\'][$i][\'connect_type\'] = \'tcp\';
$cfg[\'Servers\'][$i][\'compress\'] = false;
$cfg[\'Servers\'][$i][\'auth_type\'] = \'config\';
$cfg[\'Servers\'][$i][\'user\'] = \'root\';
$cfg[\'Servers\'][$i][\'password\'] = \'\';
if (strpos(PHP_OS, \'WIN\') !== false) {
$cfg[\'UploadDir\'] = getcwd();
} else {
$cfg[\'UploadDir\'] = \'/tmp/pharphpmyadmin\';
@mkdir(\'/tmp/pharphpmyadmin\');
@chmod(\'/tmp/pharphpmyadmin\', 0777);
}' ;
$a -> setStub ( '<?php
Phar::interceptFileFuncs();
Phar::webPhar("phpMyAdmin.phar", "phpMyAdmin-2.11.3-english/index.php");
echo "phpMyAdmin is intended to be executed from a web browser\n";
exit -1;
__HALT_COMPILER();
' );
$a -> stopBuffering ();
?>
[#1] ch1902 [2014-03-27 13:14:09]
If you are going to be running a webPhar from the browser, for example http://localhost/myphar.phar then you will probably have to associate the .phar extension with PHP in your webserver to interpret the PHP code. In Apache modify httpd.conf to include
AddType application/x-httpd-php .php .phar
[#2] frame86 at live dot com [2013-06-29 23:46:20]
The openssl example is completely wrong. The public key must be extracted from certificate and openssl_pkey_export() is for private key only.
Working example:
<?php
$publicKey = openssl_get_publickey(file_get_contents('certificate.pem'));
$details = openssl_pkey_get_details($publicKey);
file_put_contents('my.phar.pubkey', $details['key']);
?>
No need to say that the best and strongest encryption of my.phar/.phar/signature.bin is useless if the consumer does not check against a valid fingerprint or certificate of public key as anybody can open, read, recreate and sign a new archive with new key. Do you do? Think about it.
[#3] shaun at shaunfreeman dot co dot uk [2010-09-27 03:06:33]
If you are trying to use Phar for a web application and just getting a blank screen, if you have enabled suhosin as well you have to add:
suhosin.executor.include.whitelist="phar"
to "/etc/php5/conf.d/suhosin.ini" file or your "php.ini" file.
once done everything works fine and dandy.