Documentation
Distribute as a PHAR Archive
Build a standalone PHAR archive to ease the distribution of your application
On this page
Introduction#
Every Laravel Zero project may be compiled into a standalone PHAR archive — a single file containing all of your application's code and its dependencies. Anyone with PHP installed may then run it, without cloning your repository or running composer install.
Laravel Zero uses Box to provide fast application bundling. Box is included with the framework, so there is nothing to install.
Note: If you would like to distribute your application to people who don't have PHP at all, take a look at building a single executable binary.
Building Your Application#
You may compile your application using the app:build Artisan command:
php application app:build movie-cli
You will be asked for a build version, which will be baked into the archive as the value of your app.version configuration option. Once the build finishes, the archive is placed in your project's builds directory, ready to be executed:
./builds/movie-cli
Or, on Windows:
C:\application\path> php builds\movie-cli
Non-Interactive Builds#
When building from a script or a continuous integration pipeline, you will not want to be asked for the build version. You may provide it upfront using the --build-version option:
php application app:build movie-cli --build-version=1.0.0
The build process is also subject to a timeout of 300 seconds. Larger applications may need more time, which you may grant using the --timeout option. Pass 0 to disable the timeout entirely:
php application app:build movie-cli --timeout=600
Configuring the Build#
The contents of the archive are determined by the box.json file at the root of your project. A fresh application includes the app, bootstrap, config, and vendor directories:
{ "chmod": "0755", "directories": [ "app", "bootstrap", "config", "vendor" ], "files": [ "composer.json" ], "exclude-composer-files": false, "compression": "GZ" }
If your application relies on other directories at runtime — such as database or resources — you should add them to the directories array. Consult the Box configuration documentation for the full list of available options.
Debugging a Failed Build#
Builds fail for a number of reasons, but a typical pitfall is a missing ext-* dependency in the PHP installation performing the build — for example, when building inside a Docker container or a CI runner.
Running the build with increased verbosity will surface the output of Box:
php application app:build movie-cli -v
If that isn't enough, you may invoke Box directly with its --debug option:
./vendor/laravel-zero/framework/bin/box compile --working-dir=/project/path --config=/project/path/box.json --debug
What Changes in a Build#
Two things are true of your application inside an archive that are not true during development, and both affect how you write your commands:
- The environment becomes
production. Development commands such asapp:build,app:install,make:command, andtestare no longer registered. You may remove additional commands using theremoveoption of yourconfig/commands.phpconfiguration file. - The filesystem becomes read-only. Nothing inside the archive may be written to. This affects writing files, log files, compiled Blade views, and SQLite databases.
If the dotenv component is installed, your application will also load a .env file placed in the same directory as the archive, which allows the people using your application to configure it without rebuilding.
Distributing via Packagist#
To distribute your application via Packagist, so that it may be installed with composer global require, you need to make a few changes to your composer.json and box.json files.
Within your composer.json file, move the laravel-zero/framework dependency — along with any other dependency already bundled in your archive — from require to require-dev, leaving the supported PHP versions and required extensions in place. Then, point the bin entry at your build:
- "require": { - "laravel-zero/framework": "^13.0" - }, + "require-dev": { + "laravel-zero/framework": "^13.0" + }, - "bin": ["movie-cli"] + "bin": ["builds/movie-cli"]
Within your box.json file, you should add:
"exclude-dev-files": false,
The reason for these changes is that Composer installs all non-development dependencies by default. Those dependencies are already contained within the archive, so converting them to development dependencies means Composer will skip them altogether — which also ensures they can't conflict with other globally installed packages.
Finally, build your application once more, and you are ready to publish it:
php application app:build movie-cli
composer global require your-vendor/movie-cli
Self Updating#
The self-update component adds a self-update command to your built application, which downloads the latest version from your repository if one is available. You may install it using the app:install Artisan command:
php application app:install self-update
Once the component is installed, the people using your application may update it in place:
./movie-cli self-update
Update Strategies#
The self-updater uses "strategies" to determine where a new version should be downloaded from. Laravel Zero ships with three:
| Strategy | Description |
|---|---|
LaravelZero\Framework\Components\Updater\Strategy\GithubStrategy |
Downloads the archive from a builds/ directory in the GitHub repository. This is the default. |
LaravelZero\Framework\Components\Updater\Strategy\GithubReleasesStrategy |
Downloads the archive from GitHub release assets. |
LaravelZero\Framework\Components\Updater\Strategy\GitlabStrategy |
Downloads the archive from a builds/ directory in the GitLab repository. |
To choose a different strategy, first publish the component's configuration file:
php application vendor:publish --provider="LaravelZero\Framework\Components\Updater\Provider"
Then, update the strategy option within your config/updater.php configuration file:
use LaravelZero\Framework\Components\Updater\Strategy\GithubReleasesStrategy; 'strategy' => GithubReleasesStrategy::class,
You are also free to write a strategy of your own. Custom strategies must implement the StrategyInterface interface.
Spotted a mistake? Edit this page on GitHub.