Creating Phar Files
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
try
{
$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/env 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__ . "/{$pharFile}", 0770);
echo "$pharFile successfully created" . PHP_EOL;
}
catch (Exception $e)
{
echo $e->getMessage();
}
Build the Phar
Now just execute that script to create your fresh phar file with the folowing command:
php --define phar.readonly=0 create-phar.php
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).
For Reference - Temporarily Disabling phar.readonly
You don't need to do this if you used the php -dphar.readonly=0
when creating the phar, but this info may be good for reference.
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
For Reference - Re-enable phar.readonly
You don't need to do this if you used the php -dphar.readonly=0
when creating the phar, but this info may be good for reference.
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
First published: 16th August 2018