Search by

humbug / php-scoper

theofidry

Prefixes all PHP namespaces in a file or directory.

Package info

github.com/humbug/php-scoper

pkg:composer/humbug/php-scoper

Statistics

Installs: 3 871 347

Dependents: 36

Suggesters: 1

Stars: 811

Open Issues: 27

0.18.20 2026-10-08 08:21 UTC

README

Package version Build Status License

PHP-Scoper moves any body of code, including all its dependencies such as vendor directories, to a new and distinct namespace.

Goal

PHP-Scoper's goal is to ensure that all the code of a project lies in a distinct PHP namespace. This is necessary, for example, when building PHARs that:

  • bundle their own vendor dependencies; and
  • load or execute code from arbitrary PHP projects with similar dependencies.

When a package, possibly in different versions, is found both in a PHAR and in the executed code, the one from the PHAR is used. Such PHARs therefore risk conflicts between their bundled dependencies and those of the project they interact with. Due to mismatched or unsupported package versions, the resulting issues can be very difficult to debug.

Table of Contents

Usage

php-scoper add-prefix

This prefixes all the relevant namespaces of the code found in the current working directory. The prefixed files are written to a build directory, and can then be used to build your PHAR.

Warning: if you rely on Composer for autoloading, you must dump the autoloader again after prefixing the files.

For a more concrete example, refer to PHP-Scoper's build step in the Makefile. This is particularly relevant if you use Composer, as there are steps to consider both before and after running PHP-Scoper.

Building a Scoped PHAR

With Box

If you use Box to build your PHAR, you can rely on its PHP-Scoper integration. Box takes care of most of the process, so you should only need to adjust the PHP-Scoper configuration to your needs.

Without Box

Step 1: Configure build location and prep vendors

Assuming you do not need any development dependencies, run:

composer install --no-dev --prefer-dist

This saves time during scoping, as unnecessary files are not processed.

Step 2: Run PHP-Scoper

PHP-Scoper copies the code to a new location during prefixing, leaving your original code untouched. The default location is ./build, which can be changed with the --output-dir option. By default, PHP-Scoper also generates a random prefix, which can be set explicitly with the --prefix option. When automating builds, use the --force option to overwrite any existing code in the output directory without a confirmation prompt.

The basic command, with the default options, run from your project's root directory is:

bin/php-scoper add-prefix

As no path argument is given, the entire current working directory is scoped to ./build. Prefixing is limited to PHP files and scripts; other files are copied unchanged, with the exception of certain Composer-related files, which are also scoped.

If you depend on the Composer autoloader, the next step is to dump it so that everything works as expected:

composer dump-autoload --working-dir build --classmap-authoritative

Recommendations

There are three aspects to manage when dealing with isolated PHARs:

  • The PHAR format: some functions are incompatible with it, such as realpath(), which no longer works for files within the PHAR as their paths are virtual.
  • Code isolation: due to the dynamic nature of PHP, isolating your dependencies is never trivial. You should therefore have end-to-end tests to ensure your isolated code works correctly. You will also likely need to configure the excluded and exposed symbols, or patchers.
  • The dependencies: which dependencies do you ship? Tightly controlled ones, managed with a composer.lock, or always the latest versions? The latter, although preferable, is by design more brittle, as any new release of a dependency may break something. Even if the changes are SemVer compliant, the code is isolated and shipped in a PHAR.

Consequently, you should have end-to-end tests for, at a minimum, your released PHAR.

As addressing all three aspects at once can be tedious, it is highly recommended to have separate tests for each step.

For example, you can test both your non-isolated PHAR and your isolated PHAR to identify which step causes an issue. If the isolated PHAR does not work, you can test the isolated code directly, outside the PHAR, to rule out the scoping process.

There are several ways to check whether the isolated code works correctly:

Debugging

A breakdown such as the one described in Recommendations helps identify where an issue originates. However, if you are unsure or are adjusting patchers, you can check the result for a single file without running the whole scoping process:

php-scoper inspect path/to/my-file.php

Contributing

Contribution Guide

Credits

The project was originally created by Bernhard Schussek (@webmozart) and has since moved under the Humbug umbrella.