First look at PHAR

With the release of PHP 5.3 a number of new features and extensions were introduced in the languge like Namespaces, Lambda functions, Late static binding. However one powerful but underutilized feature that has not attracted a lot of fanfare yet is the addition of the PHAR extension. PHAR stands for PHp ARchive. Heard it before ? In fact the functionality has been around as PECL extension and can be used with previous PHP versions (minimum 5.2 needed) also. More on the PECL extension at Phar PECL page. For this post I'll assume that you have the PHP 5.3.

What's the use of PHAR ? If you weren't living in the caves for a long time away from the programming world you would probably have heard of or used a JAR file from the Java family, well PHAR files are to PHP what JAR files are to Java to describe in short. Phar is an archiving utility for PHP and can do more than what a JAR file does as its speciifcally made for the web applications. This blog only introduces you to PHAR and explains some of the main concepts. For a complete description of the functions of PHAR refer to the PHP Manual.

So whats in it for me you ask ? here's mainly what the PHAR can do for you
- Provides you with a convenient way to distribute a complete PHP application in a single file and run it from that file without the need to extract it to disk.
- You can execute PHP archives as easily as any other file, both on the commandline and from a web server.
- You can compress either the complete phar or files inside it.
- You can create TAR, ZIP and PHAR archives and convert between them easily using a single command.

Sounds good ? ok, let's first jump on to the "welcome" example (the twin brother of the "hello world" example) before we move on to the complexities and delve deeper.


One thing to make sure before you create or write to any phar archive apart for making the directory writable is that you must set the php.ini setting "phar.readonly" to off else you won't be able to write a phar file.

phar.readonly = off

Note that this is for development server only. You should not have this setting to off on a production server else there are chances that a php based virus could plague your application when coupled with some other vulnerability.


You may also want to process the '.phar' file as '.php' and hence may add something like this to your httpd.conf assuming that using apache webserver.

AddType application/x-httpd-php .phar

If you don't have access to httpd.conf or don't know about these configurations or simply feel lazy and don't like to do this you could skip this and simply rename your final '.phar' to '.phar.php' and it will still work.

Let's jump to the code now :

CODE:
  1. $phar = new Phar('welcome.phar'); // or welcome.phar.php
  2. $phar["welcome.txt"] = "Welcome to the Phar World";

On running this code you should be able to see a welcome.phar file in the same directory as the write.php file,

How about reading this archive, No problem, just 1 line of code is all you need !

CODE:
  1. echo file_get_contents("phar://welcome.phar/welcome.txt");

That was easy ? Let us now take a closer look at what makes up a phar file
The phar archive consists of 4 main parts :

  1. Stub :
    - It is a kind of bootstrap file (or a loader) thats initiated whenever a '.phar' is executed i.e when its directly included.
    - Its 'not' used when you directly include a file inside a phar, but is used when you include a phar file directly.
    - The stub file must end with a call to __HALT_COMPILER() token if used, a closing ?> may follow not more than just white one space.
  2. Manifest : A list describing the contents of the files in the phar, basically used save the state of the file when adding into or extracting from the phar.
  3. the file contents
  4. Optional Signature : For verifying the phar integrity.Four such signatures are supported :
    - MD5
    - SHA1
    - SHA256
    - SHA512

Ok, now that we have an insight on the biology of a phar archive, lets move onto a slightly more realistic example
Consider you have a blog application with say the following structure.
- front.php
- library/blog.class.php
- images/wow.jpg
- add.php
- edit_del.php
- cli.php

we won't dig on the actual code inside each file which can be implemented as you want.

Now, we get on with the actual code to build up our slim and trim blog.phar

CODE:
  1. $phar = new Phar('blog.phar');
  2. $phar->addFile('front.php');
  3. $phar->addFile('cli.php');
  4. $phar->addFile('add.php');
  5. $phar->addFile('edit_del.php');
  6. $phar->addFile('library/blog.class.php');
  7. $phar->addFile('images/wow.jpg');
  8. $phar->setDefaultStub('cli.php', 'front.php');

Lets understand whats going on: In the first line we simply indicated that we want a phar file named 'blog.phar'. From second onwards we just added up files and folders from the current directory. At last we just told the phar archive to execute the cli.php first if accessed from commadline or the front.php if accessed from the browser. Note again that this is a simple example and there are many more useful arguments you could use in each call if that's suitable for your application.

When you access the url to create.php using your web pal i.e any browser or execute this through command line like below:

CODE:
  1. php create.php

Abrakadabra! Honey, I shrunk the application!
You should see a compact easy to carry 'blog.phar'. Again a point to remember is that its a php archive and at the moment no compression has been applied to it. You can access the individual files same as you would if it was a folder, like if you want to see the image wow.jpg : http://url/to/phar/blog.phar/images/wow.jpg. Wasn't that neat ?

We can also add a signature to the phar file : lets set a MD5 signature

CODE:
  1. $phar->setSignatureAlgorithm(Phar::MD5); // You can have Phar::SHA1, Phar::SHA256, Phar::SHA512 also

Thats not the end you can do much more than that, like you can convert this phar between other formats like zip and tar.
No, you don't have to start from scratch just one command :

CODE:
  1. $zip = $phar->convertToData(Phar::ZIP);

how about a '.tgz'

CODE:
  1. $tgz = $zip->convertToData(Phar::TAR, Phar::BZ2, '.tbz');

In the above we have also applied the BZ2 compression. You can compress / decompress the complete archive or the files inside. We can go on and on. however, its timeup folks. If you found this useful and love sequels put up a comment and we could have have a "PHAR Reloaded" with more exciting and useful stuff. As usual any bug reports, comments and suggestions are welcome.

IMP Note: Executing PHARs directly  as indicated above did not work properly with XAMPP on linux and had a garbage character output issue.

About Jatin Chimote

Jatin has been working with PHP for the last 7 years and is a Zend Certified PHP 5 Engineer.

3 Responses to First look at PHAR

  1. a_musing_moose May 6, 2010 at 8:15 am #

    Totally agree, Phar files are one of the much overlooked aspects of PHP 5.3. My thoughts on the subject as very similar to yours.

    I do see some other uses for phar files beyond simply packaging up a whole application. For example, how about packaging up re-usable libraries as phar files? I use this approach with a library I wrote. In this case the stub included registers it own autoloader for files witihin the library. From then on I can use any class in the library simply be including the phar file in my index page.

    If you are interested take a look at: A Galaxy Phar Phar Away

    • Jatin Chimote May 6, 2010 at 8:52 am #

      Jon (Moose) - Yup, I agree its use it not limited to just packaging, I think a whole lot of other possibilities need to be explored. Your idea is great. Thanks for the post.

Trackbacks/Pingbacks

  1. [How To] Use of PHP’s fileinfo extension to get file’s MIME type at SANIsoft – PHP for E Biz - May 17, 2010

    [...] previous post, one of my colleague Jatin introduced you to one of the new features of PHP-5.3, PHAR. I am going to take a look at one more PHP-5.3 feature Fileinfo which was a PECL extension prior to [...]

Leave a Reply