@baileyherbert/packr

Command line tool for packaging PHP projects into single files.

Usage no npm install needed!

<script type="module">
  import baileyherbertPackr from 'https://cdn.skypack.dev/@baileyherbert/packr';
</script>

README

Packr


Packr is a command line tool that bundles a PHP project into a single file, along with its dependencies, assets, and any other necessary files. The bundled file can be used like any other PHP script, including through the command line and on a web server. Internally, source code is loaded through autoloading which can be customized, or inferred from Composer.



Introduction

Installation

To start using the tool, you must install it globally using npm. After installation completes, you will be able to call the packr command globally.

npm install -g @baileyherbert/packr

Server requirements

The generated bundles will work on PHP 5.4 and greater. There are no extension requirements except zlib for inflation (which can be disabled per project).

Planned features

This command line tool is still under development. I am planning on adding the following features soon:

  • Composer support
  • Better error handling when debugging
  • Glob pattern support in configuration files

Getting started

Creating a project

First, create a new directory and a file inside it called packr.json. This is your configuration file and is required to use the tool. Have a look at the basic template for an example.

Next, create your source directory. In the basic template linked above, we are using src for the App\ namespace, so create a new directory called src inside your project. We'll put our source files in there.

Now you need to create your main method which Packr will call when the bundle is executed. This is, by default, done through the Application class as described in the next section.

Application class

Now you need to create your main class and method. This is App\Application::main by default and can be configured through the main configuration option. Create a file at src/Application.php:

<?php

namespace App;

class Application {
    public static function main() {
        echo "Hello world!";
    }
}

Finally, open a terminal in the project's root directory and run packr build. A bundle file called bundle.php will be created in the same directory. You can run it with PHP or through a web server:

> php bundle.php
Hello world!

Command line tool

Build a bundle

To bundle an existing project, open a terminal in the project's root directory, which should contain your packr.json configuration file. If you still need to set up your configuration file, see the configuration docs.

packr build [--debug -D]

Build a bundle and watch for changes

You may wish to run the tool continuously and have it automatically build the bundle whenever you modify the configuration file or source files.

packr watch [--debug -D]

Expand a bundle

This tool includes an expansion feature which will convert a bundle back into the original project. The resulting project will include the configuration file, embedded files, and source files in their original directories.

packr expand <bundle> <target> [--force -F]
  • <bundle> – Path to the bundled .php file you wish to expand.
  • <target> – Path to a directory under which the files will be unpacked. This is created if it does not exist.

If the <target> directory is not empty, you will encounter an error. To silence this error and forcefully overwrite the contents, append the --force flag.

Get info about a bundle

Each bundle contains encoded information that may be useful under some circumstances, such as the time the bundle was built, the author and version of the bundle, and the size and compression of its embedded files. You can view this information from the command line.

packr info <bundle>
  • <bundle> – Path to the bundled .php file you wish to get information on.

Configuration

Each project must have a configuration file called packr.json at its root. The options in this file allow you to customize how the bundle is generated and specify which files and source code to include.

Basic template

This is a basic starter template for your packr.json file. Continue reading for information about each configuration option.

{
    "version": "1.0.0",
    "author": "John Doe <john.doe@example.com>",
    "namespaces": {
        "App\\": "src/"
    }
}

Available options

This is a list of all available configuration options. If your file specifies options that are not in this list, you will receive an error.

Name Type Description
version string The version of the bundle in no particular format. This is visible to anyone with access to the bundle. Defaults to 1.0.0.
author string The author of the bundle in no particular format. This is visible to anyone with access to the bundle.
main string The full name of a class and a static method to call when the bundle is executed. Defaults to App\Application::main.
out string The name or path of the bundle file to which output will be written. Relative paths are resolved relative to the project's root directory. Defaults to bundle.php.
namespaces object An object containing your PHP namespaces and their source directories. The key is always the namespace prefix and the value is always a path to a directory containing source files under that namespace.
files object An object containing the files to embed in the bundle. The key is always a name or identifier for the file (used to retrieve it from within the bundle), and the value is a path to the file.
encoding string The type of encoding and/or compression to use. The current allowed values are deflate (default) and base64.
file_compression string The type of compression to use for embedded files. The current allowed values are deflate or null (default) to disable.

Namespaces

Packr works based on PSR standards, including namespaces. It does not support the embedding of classes which are not under a namespace, and each class must have its own file under directories that match the namespace.

For example, if the configuration file is set to map App\ to src/, then a class whose full name is App\Util\ZipArchive must be defined at src/Util/ZipArchive.php.

Embedding files

You may wish to embed files with the bundle. As an example, if you're creating an installer for an app, you may want to create a zip archive of the app's files and embed it in the installer. Packr has native support for this. Here's how to implement such an example:

First, add the file to the files directive in your configuration.

{
    "version": "1.0.0",
    "namespaces": {},
    "files": {
        "app_files": "path/to/archive.zip"
    }
}

Then, you can use the Packr\Bundle class to retrieve the file from within your code. This class is always included in the bundle. For example, in our main method:

namespace App;

use Packr\Bundle;

class Application {
    public static function main() {
        $contents = Bundle::getFile('app_files');
    }
}

The $contents variable in the code above will contain the raw binary content of the file. You can then save this file to the disk or a temporary file and use ZipArchive to extract it, or use a third party library to directly extract it from memory.

If you're working with large embedded files, you can also buffer it. This feature is only available when the file_compression option is set to null.

Bundle::getFile('app_files', function($chunk) {
    echo $chunk;
}, 4096);

In the above example, the anonymous function in the second argument will receive the file in chunks of 4096 bytes as defined by the third argument. If not specified, the third argument defaults to 4096 bytes.

Compression

The encoding configuration option controls how your source code is embedded into the file.

  • The default value is deflate, which will first compress the source code and then encode it in base64 before writing it to the bundle. This can significantly reduce the overall size of the bundle, but will slow down bundles with a large number of classes.
  • Setting this to base64 will skip compression of source files, but they will still be encoded with base64. In this case, the bundle will often be larger than the original source files.

The file_compression configuration option controls whether or not embedded files such as zip archives will be compressed.

  • The default value is null which disables compression entirely. The contents of any embedded files are directly appended to the bundle with no modification. Retrieving files will be faster, but the overall bundle size and memory usage will be negatively impacted.
  • Setting this to deflate will use the deflate algorithm to compress embedded files. Retrieving files will be slower, but the overall bundle size and memory usage will decrease. Note that archives such as zip files are already compressed and that they will likely not deflate by more than a few percent.

Note that compression requires the zlib extension to be enabled in PHP. If it is not enabled, a relevant error will be printed on the screen when attempting to execute the bundle.