Package code in a PHP archive: PHAR

Appeared with PHP 5.3, our favorite language (at least mine) proposes to pack its code in a Phar archive just as java proposes it with the Jar. From my experience it is Composer who first made me use the phar, followed by PHPUnit and all the quality control tools of the code. Only recently have I started to use the utility of packaging my code in phar files. And we must recognize that having a single file to deploy on multiple servers is still more convenient than a folder and we also win all the time of configuration / installation vendors among others.

At first I wanted to create the same phar for my project via PHP's Phar API. But it's a bit of a titanic job. So I looked for ways to be more efficient, there are a lot of tools on Github that can easily create a Phar. I chose clue/phar-composer for its simplicity. As the name suggests, this tool uses dial and so requires a composer.json file at the root of the project to use it.

I realized a little program that allows me to validate the completeness of user passwords. Not inspired, I called this project crackme. This is what the composer.json file looks like:

{ "name" : "crackme" , "license" : "proprietary" , "type" : "project" , "autoload" : { "psr-4" : { "" : "src/" } } , "require" : { "php" : ">=5.4.0" , "symfony/console" : "~2.7" , "symfony/yaml" : "~2.7" , "monolog/monolog" : "~1.17" , "doctrine/dbal" : "~2.5" , "swarrot/swarrot" : "~2.1" , "videlalvaro/php-amqplib" : "~2.5" } , "bin" : [ "crackme" ] }

What is important here is the last line, I indicate my executable, a php script, but without its extension. The file must have execute rights.

The crackme file

#!/usr/bin/env php <?php require_once __DIR__ . '/vendor/autoload.php' ; use Symfony\Component\Console\Application ; use Crackme\Command\CrackIt ; define ( 'ROOT_PATH' , realpath ( '.' ) ) ; $application = new Application ( 'Crack me' , '1.0-dev' ) ; $application -> add ( new CrackIt ( ) ) ; $application -> run ( ) ;

On the first line of the file, I specify the interpreter to be used.

Inside a phar, the root is no longer the root of the hard disk but the root inside the phar; which does not pose any problem to access the files in the phar but complicates the things for those outside. I defined the constant ROOT_PATH on the current path to have a reference of the path on the hard disk where is my phar.

The rest of my code is in the src / folder but could be at the root and has nothing specific about the fact that it will be used in a phar.

To compile the phar I need phar-composer that I downloaded there and of course Composer on my machine. I made a symbolic link to compose in /usr/bin under the name "composer". Composer-phar tries to access it in the event that vendors are not installed and must be. It only remains to launch the build.

php -d phar.readonly=off . / phar-composer.phar build . / crackme /

We must disable the read-only on phar in php.ini, but not wanting to do it globally on the machine, I specify it in my command line. After a few logs, the compilation ends and I get a crackme.phar file that I can run without having to pass the interpreter.

There are other options, other tools to create phar, everything depends on your need, mine being rather basic phar-compose responds very well. Since this first experiment, I multiplied the use of phar.