<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Using Phar Archives: Introduction</title> </head> <body><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="phar.using.html">Using Phar Archives</a></div> <div class="next" style="text-align: right; float: right;"><a href="phar.using.stream.html">Using Phar Archives: the phar stream wrapper</a></div> <div class="up"><a href="phar.using.html">Using Phar Archives</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div><hr /><div id="phar.using.intro" class="section"> <h2 class="title">Using Phar Archives: Introduction</h2> <p class="para"> 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: </p> <div class="example-contents screen"> <div class="cdata"><pre> php coolapplication.phar </pre></div> </div> <p class="para"> Using a Phar archive library is identical to using any other PHP library: </p> <p class="para"> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">include </span><span style="color: #DD0000">'coollibrary.phar'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> <p class="para"> The <em>phar</em> stream wrapper provides the core of the phar extension, and is explained in detail <a href="phar.using.stream.html" class="link">here</a>. The phar stream wrapper allows accessing the files within a phar archive using PHP's standard file functions <span class="function"><a href="function.fopen.html" class="function">fopen()</a></span>, <span class="function"><a href="function.opendir.html" class="function">opendir()</a></span>, and others that work on regular files. The <em>phar</em> stream wrapper supports all read/write operations on both files and directories. </p> <p class="para"> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">include </span><span style="color: #DD0000">'phar://coollibrary.phar/internal/file.php'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">header</span><span style="color: #007700">(</span><span style="color: #DD0000">'Content-type: image/jpeg'</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">// phars can be accessed by full path or by alias<br /></span><span style="color: #007700">echo </span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #DD0000">'phar:///fullpath/to/coollibrary.phar/images/wow.jpg'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> <p class="para"> The <a href="class.phar.html" class="classname">Phar</a> class implements advanced functionality for accessing files and for creating phar archives. The Phar class is explained in detail <a href="phar.using.object.html" class="link">here</a>. </p> <p class="para"> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">try {<br /> </span><span style="color: #FF8000">// open an existing phar<br /> </span><span style="color: #0000BB">$p </span><span style="color: #007700">= new </span><span style="color: #0000BB">Phar</span><span style="color: #007700">(</span><span style="color: #DD0000">'coollibrary.phar'</span><span style="color: #007700">, </span><span style="color: #0000BB">0</span><span style="color: #007700">);<br /> </span><span style="color: #FF8000">// Phar extends SPL's DirectoryIterator class<br /> </span><span style="color: #007700">foreach (new </span><span style="color: #0000BB">RecursiveIteratorIterator</span><span style="color: #007700">(</span><span style="color: #0000BB">$p</span><span style="color: #007700">) as </span><span style="color: #0000BB">$file</span><span style="color: #007700">) {<br /> </span><span style="color: #FF8000">// $file is a PharFileInfo class, and inherits from SplFileInfo<br /> </span><span style="color: #007700">echo </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">getFileName</span><span style="color: #007700">() . </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br /> echo </span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">getPathName</span><span style="color: #007700">()) . </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">; </span><span style="color: #FF8000">// display contents;<br /> </span><span style="color: #007700">}<br /> if (isset(</span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'internal/file.php'</span><span style="color: #007700">])) {<br /> </span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'internal/file.php'</span><span style="color: #007700">]-></span><span style="color: #0000BB">getMetadata</span><span style="color: #007700">());<br /> }<br /><br /> </span><span style="color: #FF8000">// create a new phar - phar.readonly must be 0 in php.ini<br /> // phar.readonly is enabled by default for security reasons.<br /> // On production servers, Phars need never be created,<br /> // only executed.<br /> </span><span style="color: #007700">if (</span><span style="color: #0000BB">Phar</span><span style="color: #007700">::</span><span style="color: #0000BB">canWrite</span><span style="color: #007700">()) {<br /> </span><span style="color: #0000BB">$p </span><span style="color: #007700">= new </span><span style="color: #0000BB">Phar</span><span style="color: #007700">(</span><span style="color: #DD0000">'newphar.tar.phar'</span><span style="color: #007700">, </span><span style="color: #0000BB">0</span><span style="color: #007700">, </span><span style="color: #DD0000">'newphar.tar.phar'</span><span style="color: #007700">);<br /> </span><span style="color: #FF8000">// make this a tar-based phar archive, compressed with gzip compression (.tar.gz)<br /> </span><span style="color: #0000BB">$p </span><span style="color: #007700">= </span><span style="color: #0000BB">$p</span><span style="color: #007700">-></span><span style="color: #0000BB">convertToExecutable</span><span style="color: #007700">(</span><span style="color: #0000BB">Phar</span><span style="color: #007700">::</span><span style="color: #0000BB">TAR</span><span style="color: #007700">, </span><span style="color: #0000BB">Phar</span><span style="color: #007700">::</span><span style="color: #0000BB">GZ</span><span style="color: #007700">);<br /><br /> </span><span style="color: #FF8000">// create transaction - nothing is written to newphar.phar<br /> // until stopBuffering() is called, although temporary storage is needed<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">-></span><span style="color: #0000BB">startBuffering</span><span style="color: #007700">();<br /> </span><span style="color: #FF8000">// add all files in /path/to/project, saving in the phar with the prefix "project"<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">-></span><span style="color: #0000BB">buildFromIterator</span><span style="color: #007700">(new </span><span style="color: #0000BB">RecursiveIteratorIterator</span><span style="color: #007700">(new </span><span style="color: #0000BB">DirectoryIterator</span><span style="color: #007700">(</span><span style="color: #DD0000">'/path/to/project'</span><span style="color: #007700">)), </span><span style="color: #DD0000">'/path/to/'</span><span style="color: #007700">);<br /><br /> </span><span style="color: #FF8000">// add a new file via the array access API<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'file1.txt'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'Information'</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">$fp </span><span style="color: #007700">= </span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #DD0000">'hugefile.dat'</span><span style="color: #007700">, </span><span style="color: #DD0000">'rb'</span><span style="color: #007700">);<br /> </span><span style="color: #FF8000">// copy all data from the stream<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'data/hugefile.dat'</span><span style="color: #007700">] = </span><span style="color: #0000BB">$fp</span><span style="color: #007700">;<br /><br /> if (</span><span style="color: #0000BB">Phar</span><span style="color: #007700">::</span><span style="color: #0000BB">canCompress</span><span style="color: #007700">(</span><span style="color: #0000BB">Phar</span><span style="color: #007700">::</span><span style="color: #0000BB">GZ</span><span style="color: #007700">)) {<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'data/hugefile.dat'</span><span style="color: #007700">]-></span><span style="color: #0000BB">compress</span><span style="color: #007700">(</span><span style="color: #0000BB">Phar</span><span style="color: #007700">::</span><span style="color: #0000BB">GZ</span><span style="color: #007700">);<br /> }<br /><br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'images/wow.jpg'</span><span style="color: #007700">] = </span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #DD0000">'images/wow.jpg'</span><span style="color: #007700">);<br /> </span><span style="color: #FF8000">// any value can be saved as file-specific meta-data<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'images/wow.jpg'</span><span style="color: #007700">]-></span><span style="color: #0000BB">setMetadata</span><span style="color: #007700">(array(</span><span style="color: #DD0000">'mime-type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'image/jpeg'</span><span style="color: #007700">));<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">[</span><span style="color: #DD0000">'index.php'</span><span style="color: #007700">] = </span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #DD0000">'index.php'</span><span style="color: #007700">);<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">-></span><span style="color: #0000BB">setMetadata</span><span style="color: #007700">(array(</span><span style="color: #DD0000">'bootstrap' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'index.php'</span><span style="color: #007700">));<br /><br /> </span><span style="color: #FF8000">// save the phar archive to disk<br /> </span><span style="color: #0000BB">$p</span><span style="color: #007700">-></span><span style="color: #0000BB">stopBuffering</span><span style="color: #007700">();<br /> }<br />} catch (</span><span style="color: #0000BB">Exception $e</span><span style="color: #007700">) {<br /> echo </span><span style="color: #DD0000">'Could not open Phar: '</span><span style="color: #007700">, </span><span style="color: #0000BB">$e</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> <p class="para"> 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 <span class="function"><a href="phardata.setsignaturealgorithm.html" class="function">Phar::setSignatureAlgorithm()</a></span>. In addition, the public key as extracted using this code: <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br />$public </span><span style="color: #007700">= </span><span style="color: #0000BB">openssl_get_publickey</span><span style="color: #007700">(</span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #DD0000">'private.pem'</span><span style="color: #007700">));<br /></span><span style="color: #0000BB">$pkey </span><span style="color: #007700">= </span><span style="color: #DD0000">''</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">openssl_pkey_export</span><span style="color: #007700">(</span><span style="color: #0000BB">$public</span><span style="color: #007700">, </span><span style="color: #0000BB">$pkey</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> must be saved adjacent to the phar archive it verifies. If the phar archive is saved as <em>/path/to/my.phar</em>, the public key must be saved as <em>/path/to/my.phar.pubkey</em>, or phar will be unable to verify the OpenSSL signature. </p> <p class="para"> As of version 2.0.0, The <a href="class.phar.html" class="classname">Phar</a> class also provides 3 static methods, <span class="function"><a href="phar.webphar.html" class="function">Phar::webPhar()</a></span>, <span class="function"><a href="phar.mungserver.html" class="function">Phar::mungServer()</a></span> and <span class="function"><a href="phar.interceptfilefuncs.html" class="function">Phar::interceptFileFuncs()</a></span> that are crucial to packaging up PHP applications designed for usage on regular filesystems and for web-based applications. <span class="function"><a href="phar.webphar.html" class="function">Phar::webPhar()</a></span> implements a front controller that routes HTTP calls to the correct location within the phar archive. <span class="function"><a href="phar.mungserver.html" class="function">Phar::mungServer()</a></span> is used to modify the values of the <var class="varname"><var class="varname"><a href="reserved.variables.server.html" class="classname">$_SERVER</a></var></var> array to trick applications that process these values. <span class="function"><a href="phar.interceptfilefuncs.html" class="function">Phar::interceptFileFuncs()</a></span> instructs Phar to intercept calls to <span class="function"><a href="function.fopen.html" class="function">fopen()</a></span>, <span class="function"><a href="function.file-get-contents.html" class="function">file_get_contents()</a></span>, <span class="function"><a href="function.opendir.html" class="function">opendir()</a></span>, and all of the stat-based functions ( <span class="function"><a href="function.file-exists.html" class="function">file_exists()</a></span>, <span class="function"><a href="function.is-readable.html" class="function">is_readable()</a></span> and so on) and route all relative paths to locations within the phar archive. </p> <p class="para"> 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 <em>phpMyAdmin.phar.tar.php</em> can be accessed as a regular file from your web server after modifying the user/password: </p> <p class="para"> <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">@</span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #DD0000">'phpMyAdmin.phar.tar.php'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">copy</span><span style="color: #007700">(</span><span style="color: #DD0000">'phpMyAdmin-2.11.3-english.tar.gz'</span><span style="color: #007700">, </span><span style="color: #DD0000">'phpMyAdmin.phar.tar.php'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a </span><span style="color: #007700">= new </span><span style="color: #0000BB">Phar</span><span style="color: #007700">(</span><span style="color: #DD0000">'phpMyAdmin.phar.tar.php'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">startBuffering</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #DD0000">"phpMyAdmin-2.11.3-english/config.inc.php"</span><span style="color: #007700">] = </span><span style="color: #DD0000">'<?php<br />/* Servers configuration */<br />$i = 0;<br /><br />/* Server localhost (config:root) [1] */<br />$i++;<br />$cfg[\'Servers\'][$i][\'host\'] = \'localhost\';<br />$cfg[\'Servers\'][$i][\'extension\'] = \'mysqli\';<br />$cfg[\'Servers\'][$i][\'connect_type\'] = \'tcp\';<br />$cfg[\'Servers\'][$i][\'compress\'] = false;<br />$cfg[\'Servers\'][$i][\'auth_type\'] = \'config\';<br />$cfg[\'Servers\'][$i][\'user\'] = \'root\';<br />$cfg[\'Servers\'][$i][\'password\'] = \'\';<br /><br /><br />/* End of servers configuration */<br />if (strpos(PHP_OS, \'WIN\') !== false) {<br /> $cfg[\'UploadDir\'] = getcwd();<br />} else {<br /> $cfg[\'UploadDir\'] = \'/tmp/pharphpmyadmin\';<br /> @mkdir(\'/tmp/pharphpmyadmin\');<br /> @chmod(\'/tmp/pharphpmyadmin\', 0777);<br />}'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">setStub</span><span style="color: #007700">(</span><span style="color: #DD0000">'<?php<br />Phar::interceptFileFuncs();<br />Phar::webPhar("phpMyAdmin.phar", "phpMyAdmin-2.11.3-english/index.php");<br />echo "phpMyAdmin is intended to be executed from a web browser\n";<br />exit -1;<br />__HALT_COMPILER();<br />'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">stopBuffering</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> </div><hr /><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="phar.using.html">Using Phar Archives</a></div> <div class="next" style="text-align: right; float: right;"><a href="phar.using.stream.html">Using Phar Archives: the phar stream wrapper</a></div> <div class="up"><a href="phar.using.html">Using Phar Archives</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div></body></html>