phpscoper

PHP-Scoper is a tool which essentially moves any body of code, including all dependencies such as vendor directories, to a new and distinct namespace. The tool goal is to make sure that all code for a project lies in a distinct PHP namespace. This is necessary, for example, when building PHARs that Bundle their own vendor dependencies; and load/execute code from arbitrary PHP projects with similar dependencies.

When a package (of possibly different versions) exists, and is found in both a PHAR and the executed code, the one from the PHAR will be used. This means these PHARs run the risk of raising conflicts between their bundled vendors and the vendors of the project they are interacting with, leading to issues that are potentially very difficult to debug due to dissimilar or unsupported package versions.

Installation and usage

You can simply install PHP Scoper with composer :

composer global require humbug/php-scoper

The library is not designed to be extended, but you can already use it with :

php-scoper add-prefix

This will prefix all relevant namespaces in code found in the current working directory. The prefixed files will be accessible in a build folder. You can then use the prefixed code to build your PHAR. Notice that after prefixing the files, if you are relying on Composer for the autoloading, dumping the autoloader again is required.

For a more concrete example, you can take a look at PHP-Scoper’s build step in Makefile, especially if you are using Composer as there are steps both before and after running PHP-Scoper to consider.

If you need more granular configuration, you can create a scoper.inc.php by running the command php-scoper init. A different file/location can be passed with a --config option.

<?php declare(strict_types=1);

// scoper.inc.php

use Isolated\Symfony\Component\Finder\Finder;

return [
    'prefix' => null,                       // string|null
    'finders' => [],                        // Finder[]
    'patchers' => [],                       // callable[]
    'files-whitelist' => [],                // string[]
    'whitelist' => [],                      // string[]
    'whitelist-global-constants' => true,   // bool
    'whitelist-global-classes' => true,     // bool
    'whitelist-global-functions' => true,   // bool
];

If null or empty string are giving as prefix, then a random prefix will be automatically generated. Also PHP Scoper prefix all relevant code found in the current working directory, but you can also define Finders in configuration and define which files should be scoped.

<?php declare(strict_types=1);

// scoper.inc.php

use Isolated\Symfony\Component\Finder\Finder;

return [
    'finders' => [
        Finder::create()->files()->in('src'),
        Finder::create()
            ->files()
            ->ignoreVCS(true)
            ->notName('/LICENSE|.*\\.md|.*\\.dist|Makefile|composer\\.json|composer\\.lock/')
            ->exclude([
                'doc',
                'test',
                'test_old',
                'tests',
                'Tests',
                'vendor-bin',
            ])
            ->in('vendor'),
        Finder::create()->append([
            'bin/php-scoper',
            'composer.json',
        ])
    ],
];

PHP Scoper came with tons of additional features such as Patchers, whitelisted files, Constants & Classes & functions from the global namespace, Symbols, Namespaces whitelisting, …etc. Also make sure to check PHP Scoper limitations, so you won’t waist time debugging unsupported features.

Now your project is scoped, you can package it and share your Phar files. This is a very useful tool to avoid namespaces issues in your composer dependencies, also very useful to prepare WordPress plugins before uploading them to the plugins directory, but make sure to check open issues for scoping WordPress. PHP Scoper is an open source tool released under an MIT license, more information https://github.com/humbug/php-scoper

LEAVE A REPLY

Please enter your comment!
Please enter your name here