Notes on what I needed to do to make a PHAR file, so I will find it faster next time. Article not expected to be exciting, but to save time.

Technically PHAR is modelled on a Java JAR file, with the same basic compressed file bundle and manifest meta file 1. Since PHP 5.3, phar is a standard module, and likely to be available in your interpreter 2 3.
The minimum build process is outlined 4 5 on the PHP language website. A slightly better version is on stack-overflow 6 or 7. Here is a unit test for PHARs, as someone misused the build library 8
The raw PHAR library in PHP supports BZIP2 and GZIP compression, which would make the files smaller 9. If one needs to use PHAR directly to as a website, use webPhar 10 to manage the “file path routing” automatically as (the files are bundled, there isn't any file paths).

There is a custom PHAR making project 11 that @seldaek recommended in 2011. I haven't asked him to see if the recommendation still holds. However a more recent article by @tfidry also references “state of the art” and box2. Box installed without any issues, although it did tell me to allow writing to PHAR files, which is a PHP ini setting. I need to do something to the default setup, as the source code is verbatim in the generated file. UPDATE: I mean enable compression, which the presented sample now does. It would be a much smaller file if converted to byte codes.
A different tools is 12, this one supports compression, and supports exec commands during build.
If you use phpci 13, they have integrated PHAR 14

Gotchas of PHAR

  • If you are using Box2, with compression enabled (recommended); due to the way the PHAR extension handles files; you need to set `ulimit -n` to a large number. Do not do this on production servers. If you are using win16, win32 or win64; I have no idea if or how to set this.
  • Some people report compression rates of 80%. For my scenarios, I get around 60% smaller (e.g. 3MB to 1MB).
  • You need to be careful with build paths, as the filesystem paths are different pre-PHAR and post-PHAR. With symfony, you need to hack the AppKernel quite heavily, but fortunately, all the decision points are in this single file. To access files inside the PHAR with fopen(), the paths should be in format “phar://directories/to/phar/file.phar/directories/inside/phar/file.php”. Fortunately modern class loaders can do most of this by magic.
  • Again, for Symfony, the config file “source” feature doesn't work, if you pack the config files. You can either keep all config outside of the PHAR, or inline everything into one big file. Or I suppose push a branch to symfony/config...
  • Referencing symfony again, but this would be generically applicable, the boilerplate code for bin/console and app/AppKernel etc is cumbersome to carry around. For my PHAR of CLI tools I make a custom bootstrap file which inlines the above functionality, loads the reduced config files more simply. As this bootstrap only applies to this CLI, there is no need for the user to pass in the vendor/command param. The custom bootstrap should be checked in to the bundle and repo, and avoid symfony/create-project.
  • When deploying to servers, your work should include a PHP version check; as old servers won't support PHAR.
  • I haven't used this todate; but SSL signing code (as Apple store apps, or Java beans are) is recommended for commercially retailed software.

Sample Box config file to build my clone of phpunit-skelgen

{
    "alias": "phpunit-skelgen.phar",
    "chmod": "0755",
    "directories": ["src"],
    "files": [
        "LICENSE"
    ],
    "finder": [
        {
            "name": "*.php",
            "exclude": ["Tests", "build"],
            "in": "vendor"
        }
    ],
    "git-version": "package_version",
    "main": "phpunit-skelgen",
    "output": "skelgen.phar",
    "stub": true,
	"compress":"BZ2"
}