brianhenryie / strauss
Prefixes dependencies namespaces so they are unique to your plugin
Installs: 230 742
Dependents: 9
Suggesters: 0
Security: 0
Stars: 172
Watchers: 3
Forks: 59
Open Issues: 35
pkg:composer/brianhenryie/strauss
Requires
- composer-runtime-api: ^2.0
- brianhenryie/simple-php-code-parser: ^0.15.3
- composer/class-map-generator: ^1.6.0
- composer/composer: ^2.6.0
- elazar/flystream: ^0.5.0|^1
- json-mapper/json-mapper: ^2.0.0
- league/flysystem: ^2.1|^3.0
- league/flysystem-memory: *
- monolog/monolog: ^2.10
- nikic/php-parser: ^5.4.0
- symfony/console: ^4|^5|^6|^7
- symfony/finder: ^4|^5|^6|^7
Requires (Dev)
- php: ^7.4|^8.0
- ext-json: *
- brianhenryie/color-logger: ^1.2
- clue/phar-composer: ^1.2
- jaschilz/php-coverage-badger: ^2.0
- mheap/phpunit-github-actions-printer: ^1.4
- mockery/mockery: ^1.6
- phpstan/phpstan: ^1.10
- phpunit/phpcov: *
- phpunit/phpunit: ^9|^10
- squizlabs/php_codesniffer: ^3.5
Conflicts
- json-mapper/json-mapper: 2.23.0 | 2.24.0
Replaces
- dev-master
- 0.24.1
- 0.24.0
- 0.23.0
- 0.22.6
- 0.22.5
- 0.22.4
- 0.22.3
- 0.22.2
- 0.22.1
- 0.22.0
- 0.21.1
- 0.21.0
- 0.20.1
- 0.20.0
- 0.19.5
- 0.19.4
- 0.19.3
- 0.19.2
- 0.19.1
- 0.19.0
- 0.18.0
- 0.17.0
- 0.16.0
- 0.15.0
- 0.14.1
- 0.14.0
- 0.13.0
- 0.12.0
- 0.11.1
- 0.11.0
- 0.10.4
- 0.10.3
- 0.10.2
- 0.10.1
- 0.10.0
- 0.9.0
- 0.8.10
- 0.8.9
- 0.8.8
- 0.8.7
- 0.8.6
- 0.8.5
- 0.8.4
- 0.8.3
- 0.8.2
- 0.8.1
- 0.8.0
- 0.5.0
- 0.4.0
- 0.3.0
- 0.2.2
- 0.2.0
- 0.1.0
- dev-fix-207-215-file-copy
- dev-add/SymlinkProtectFileSystem
- dev-fix-files-autoloader-require-twice
- dev-fix-208-files-aliases
- dev-fix-cleanup-after-delete-vendor-packages
- dev-fix-204-strauss-doesnt-read-custom-config
- dev-fix/prefix-contants
- dev-add/monolog
- dev-fix-190
- dev-fix-vendor-autoloader
- dev-update-dependency
- dev-fix-psr4-autoloader-189
- dev-add/189-test
- dev-add/188-tests
- dev-fix/191
- dev-fix/183
- dev-fix/166
- dev-fix/179
- dev-fix/173
- dev-patch-1
- dev-fix/171
- dev-fix/close-mockery
- dev-Add-`ComposerAutoloadGenerator`
- dev-typos-again
- dev-fix/163
- dev-fix/154
- dev-fix/remove-duplicated-silent-option
- dev-fix/159
- dev-fix/136-do-not-update-call-sites
- dev-add/alias-renamed-classes-for-dev-dependencies
- dev-issue92-plain-version
This package is auto-updated.
Last update: 2025-10-22 03:47:26 UTC
README
Strauss – PHP Namespace Renamer
A tool to prefix namespaces, classnames, and constants in PHP files to avoid autoloading collisions.
A fork of Mozart for Composer for PHP.
Have you ever activated a WordPress plugin that has a conflict with another because the plugins use two different versions of the same PHP library? Strauss is the solution to that problem - it ensures that your plugin's PHP dependencies are isolated and loaded from your plugin rather than loading from whichever plugin's autoloader registers & runs first.
⚠️ Sponsorship: It would be neat if you were to offer me a license to your plugin, or at least post about where this is used.
Table of Contents
- Installation
- As a .pharfile (recommended)
- As a dev dependency via composer (not recommended)
- Edit composer.jsonscripts
 
- As a 
- Usage
- Configuration
- Autoloading
- Motivation & Comparison to Mozart
- Alternatives
- Breaking Changes
- Acknowledgements
Installation
As a .phar file (recommended)
There are a couple of small steps to make this possible.
Create a bin/.gitkeep file
This ensures that there is a bin/ directory in the root of your project. This is where the .phar file will go.
mkdir bin touch bin/.gitkeep
.gitignore the .phar file
Add the following to your .gitignore:
bin/strauss.phar
Edit composer.json `scripts
In your composer.json, add strauss to the scripts section:
"scripts": { "prefix-namespaces": [ "sh -c 'test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/latest/download/strauss.phar'", "@php bin/strauss.phar", "@composer dump-autoload" ], "post-install-cmd": [ "@prefix-namespaces" ], "post-update-cmd": [ "@prefix-namespaces" ], "post-autoload-dump": [ "@php bin/strauss.phar include-autoloader" ] }
This provides composer strauss, which does the following:
- The sh -ccommand tests ifbin/strauss.pharexists, and if not, downloads it from releases.
- Then @php bin/strauss.pharis run to prefix the namespaces.
- Ensure that composer's autoload map is updated.
As a dev dependency via composer (not recommended)
If you prefer to include Strauss as a dev dependency, you can still do so. You mileage may vary when you include it this way.
composer require --dev brianhenryie/strauss
Edit composer.json `scripts
"scripts": { "prefix-namespaces": [ "strauss", "@php composer dump-autoload" ], "post-install-cmd": [ "@prefix-namespaces" ], "post-update-cmd": [ "@prefix-namespaces" ], "post-autoload-dump": [ "strauss include-autoloader" ] }
Usage
If you add Strauss to your composer.json as indicated in Installation, it will run when you composer install or composer update. To run Strauss directly, simply use:
composer prefix-namespaces
To update the files that call the prefixed classes, you can use --updateCallSites=true which uses your autoload key, or --updateCallSites=includes,templates to explicitly specify the files and directories.
composer -- prefix-namespaces --updateCallSites=true
or
composer -- prefix-namespaces --updateCallSites=includes,templates
To try it out without making changes, you can use the --dry-run flag:
Verbosity can be controlled with --notice (default), --info, --debug and --silent.
Configuration
Strauss potentially requires zero configuration, but likely you'll want to customize a little, by adding in your composer.json an extra/strauss object. The following is the default config, where the namespace_prefix and classmap_prefix are determined from your composer.json's autoload or name key and packages is determined from the require key:
"extra": { "strauss": { "target_directory": "vendor-prefixed", "namespace_prefix": "BrianHenryIE\\My_Project\\", "classmap_prefix": "BrianHenryIE_My_Project_", "constant_prefix": "BHMP_", "packages": [ ], "update_call_sites": false, "override_autoload": { }, "exclude_from_copy": { "packages": [ ], "namespaces": [ ], "file_patterns": [ ] }, "exclude_from_prefix": { "packages": [ ], "namespaces": [ ], "file_patterns": [ ] }, "namespace_replacement_patterns" : { }, "delete_vendor_packages": false, "delete_vendor_files": false } },
The following configuration is inferred:
- target_directorydefines the directory the files will be copied to, default- vendor-prefixed
- namespace_prefixdefines the default string to prefix each namespace with
- classmap_prefixdefines the default string to prefix class names in the global namespace
- packagesis the list of packages to process. If absent, all packages in the- requirekey of your- composer.jsonare included
- classmap_outputis a- boolto decide if Strauss will create- autoload-classmap.phpand- autoload.php. If it is not set, it is- falseif- target_directoryis in your project's- autoloadkey,- trueotherwise.
The following configuration is default:
- delete_vendor_packages:- falsea boolean flag to indicate if the packages' vendor directories should be deleted after being processed. It defaults to false, so any destructive change is opt-in.
- delete_vendor_files:- falsea boolean flag to indicate if files copied from the packages' vendor directories should be deleted after being processed. It defaults to false, so any destructive change is opt-in. This is maybe deprecated! Is there any use to this that is more appropriate than- delete_vendor_packages?
- include_modified_dateis a- boolto decide if Strauss should include a date in the (phpdoc) header written to modified files. Defaults to- true.
- include_authoris a- boolto decide if Strauss should include the author name in the (phpdoc) header written to modified files. Defaults to- true.
- update_call_sites:- false. This can be- true,- falseor an- arrayof directories/filepaths. When set to- trueit defaults to the directories and files in the project's- autoloadkey. The PHP files and directories' PHP files will be updated where they call the prefixed classes.
The remainder is empty:
- constant_prefixis for- define( "A_CONSTANT", value );->- define( "MY_PREFIX_A_CONSTANT", value );. If it is empty, constants are not prefixed (this may change to an inferred value).
- override_autoloada dictionary, keyed with the package names, of autoload settings to replace those in the original packages'- composer.json- autoloadproperty.
- exclude_from_prefix/- file_patterns
- exclude_from_copy- packagesarray of package names to be skipped
- namespacesarray of namespaces to skip (exact match from the package autoload keys)
- file_patternsarray of regex patterns to check filenames against (including vendor relative path) where Strauss will skip that file if there is a match
 
- exclude_from_prefix- packagesarray of package names to exclude from prefixing.
- namespacesarray of exact match namespaces to exclude (i.e. not substring/parent namespaces)
 
- namespace_replacement_patternsa dictionary to use in- preg_replaceinstead of prefixing with- namespace_prefix.
Autoloading
Strauss uses Composer's own tools to generate a set of autoload files in the target_directory and creates an autoload.php alongside it, so in many projects autoloading is just a matter of:
require_once __DIR__ . '/vendor-prefixed/autoload.php';
If you plan to continue using Composer's autoloader you probably want to turn on delete_vendor_packages or set target_directory to vendor.
You can use strauss include-autoloader to add a line to vendor/autoload.php which includes the autoloader for the new files.
When delete_vendor_packages is enabled, vendor/composer/autoload_aliases.php is created to allow modified classes to be loaded with their old name during development. This file should not be included in your production code.
Motivation & Comparison to Mozart
I was happy to make PRs to Mozart to fix bugs, but they weren't being reviewed and merged. At the time of writing, somewhere approaching 50% of Mozart's code was written by me with an additional nine open PRs and the majority of issues' solutions provided by me. This fork is a means to merge all outstanding bugfixes I've written and make some more drastic changes I see as a better approach to the problem.
Benefits over Mozart:
- A single output directory whose structure matches source vendor directory structure (conceptually easier than Mozart's independent classmap_directoryanddep_directory)
- A generated autoload.phptoincludein your project (analogous to Composer'svendor/autoload.php)
- Handles filesautoloaders – and any autoloaders that Composer itself recognises, since Strauss uses Composer's own tooling to parse the packages
- Zero configuration – Strauss infers sensible defaults from your composer.json
- No destructive defaults – delete_vendor_filesdefaults tofalse, so any destruction is explicitly opt-in
- Licence files are included and PHP file headers are edited to adhere to licence requirements around modifications. My understanding is that re-distributing code that Mozart has handled is non-compliant with most open source licences – illegal!
- Extensively tested – PhpUnit tests have been written to validate that many of Mozart's bugs are not present in Strauss
- More configuration options – allowing exclusions in copying and editing files, and allowing specific/multiple namespace renaming
- Respects composer.jsonvendor-dirconfiguration
- Prefixes constants (define)
- Handles meta-packages and virtual-packages
Strauss will read the Mozart configuration from your composer.json to enable a seamless migration.
Alternatives
I don't have a strong opinion on these. I began using Mozart because it was easy, then I adapted it to what I felt was most natural. I've never used these.
- humbug/php-scoper
- TypistTech/imposter-plugin
- Automattic/jetpack-autoloader
- tschallacka/wordpress-composer-plugin-builder
- Interfacelab/namespacer
- PHP-Prefixer SaaS!
Interesting
- composer-unused/composer-unused
- sdrobov/autopsr4
- jaem3l/unfuck
- bamarni/composer-bin-plugin
- phar-io/composer-distributor
Breaking Changes
- v0.21.0 – will prefix global functions
- v0.16.0 – will no longer prefix PHP built-in classes seen in polyfill packages
- v0.14.0 – psr/*packages no longer excluded by default
- v0.12.0 – default output target_directorychanges fromstrausstovendor-prefixed
Please open issues to suggest possible breaking changes. I think we can probably move to 1.0.0 soon.
Backward Compatibility Promise
This project will not increase its minimum required PHP version ahead of WordPress.
https://core.trac.wordpress.org/ticket/62622
Changes before v1.0
- Comprehensive attribution of code forked from Mozart – changes have been drastic and git blameis now useless, so I intend to add more attributions
- More consistent naming. Are we prefixing or are we renaming?
- Further unit tests, particularly file-system related
- Regex patterns in config need to be validated
- Change the name? "Renamespacer"?
Changes before v2.0
The correct approach to this problem is probably via PHP-Parser. At least all the tests will be useful.
Acknowledgements
Coen Jacobs and all the contributors to Mozart, particularly those who wrote nice issues.