Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Creating Phar Files

PHP

I write lots of helper scripts to do everyday tasks on my computer. These usually start out as BASH scripts, but quite often turn into PHP scripts/tools as they get more complex. For example, I use a PHP CLI tool for a personal password manager.

Sometimes a script turn into a "tool" that requires a couple of classes, so I stick them into a folder and have an external BASH script in my $PATH that calls the folders "entrypoint". However, wouldn't it be great if I could just package up the entire folder into a single executable file, much like Java's JAR. This is where the PHAR comes in.

If you use PHP you probably use a phar file every day in the form of composer. I had never bothered to learn how to create these files before because I assumed it would be hard, but it's actually easier than I could have believed.

Steps

Simply create a folder for your project, before creating a folder within there called "app" for your application's source code.

mkdir -p my-project/app

Copy all of your PHP files into the app folder and make the "entrypoint" file called main.php (or you can call it anything you like and modify the script below).

Below is my phar generation script. Copy it into the level just above app and call it create-phar.php or perhaps compile.php.

<?php

$pharFile = 'app.phar';

// clean up
if (file_exists($pharFile)) 
{
    unlink($pharFile);
}

if (file_exists($pharFile . '.gz')) 
{
    unlink($pharFile . '.gz');
}

// create phar
$phar = new Phar($pharFile);

// start buffering. Mandatory to modify stub to add shebang
$phar->startBuffering();

// Create the default stub from main.php entrypoint
$defaultStub = $phar->createDefaultStub('main.php');

// Add the rest of the apps files
$phar->buildFromDirectory(__DIR__ . '/app');

// Customize the stub to add the shebang
$stub = "#!/usr/bin/php \n" . $defaultStub;

// Add the stub
$phar->setStub($stub);

$phar->stopBuffering();

// plus - compressing it into gzip  
$phar->compressFiles(Phar::GZ);

# Make the file executable
chmod(__DIR__ . '/app.phar', 0770);

echo "$pharFile successfully created" . PHP_EOL;

Temporarily Disabling phar.readonly

To be able to create the phar file, we need to temporarily turn off the phar.readonly mode in our php.ini file. By default, phar files cannot be written to for security.

For me this file is found at /etc/php/7.0/cli/php.ini and I can run this BASH to disable it.

SEARCH=";phar.readonly = On"
REPLACE="phar.readonly = Off"
FILEPATH="/etc/php/7.0/cli/php.ini"
sed -i "s;$SEARCH;$REPLACE;" $FILEPATH

Build the Phar

Now just execute that script to create your fresh phar file. The phar should be executable, so you can just drop it in your $PATH and start using it like a command (perhaps rename it to remove the .phar extension if you like).

Re-enable phar.readonly

Now re-enable phar.readonly for security. You can do this by setting the value to Off, deleting the line, or commenting it out.

SEARCH="phar.readonly = Off"
REPLACE=";phar.readonly = On"
FILEPATH="/etc/php/7.0/cli/php.ini"
sed -i "s;$SEARCH;$REPLACE;" $FILEPATH

Debugging

If you get the error message below, you haven't got the line in the relevant php.ini file manually setting phar.readonly to Off. You have to have the line in there and not commented out.

PHP Fatal error:  Uncaught UnexpectedValueException: creating archive "app.phar" disabled by the php.ini setting phar.readonly in /home/stuart/Seafile/Desktop/Desktop/my-phar-project/create-phar.php:19
Stack trace:
#0 /home/stuart/Seafile/Desktop/Desktop/my-phar-project/create-phar.php(19): Phar->__construct('app.phar')
#1 {main}
  thrown in /home/stuart/Seafile/Desktop/Desktop/my-phar-project/create-phar.php on line 19

References