$npx -y skills add Lonsdale201/wp-agent-skills --skill wp-strauss-namespace-prefixingBundle Composer dependencies inside a WordPress plugin without conflicts by prefixing their namespaces, classnames, and constants with Strauss (brianhenryie/strauss, the maintained Mozart successor). Covers why shared vendor libraries collide between plugins (one PHP process, fir
| 1 | # Strauss: prefix bundled Composer dependencies |
| 2 | |
| 3 | WordPress loads every active plugin into **one PHP process**, and for any given class name, whichever plugin's Composer autoloader registers first wins. If your plugin bundles Guzzle 7 and another plugin bundles Guzzle 6, one of you silently runs the other's version — best case a subtle bug, worst case a fatal. **Strauss** solves this by copying your runtime dependencies into `vendor-prefixed/` and rewriting their namespaces, classnames, and constants so they are unique to your plugin (`GuzzleHttp\Client` becomes `My_Plugin\GuzzleHttp\Client`). This skill wires Strauss into the Composer lifecycle and the release build. It is about *bundling isolation*, not autoloading your own plugin code. |
| 4 | |
| 5 | ## When to use this skill |
| 6 | |
| 7 | - A distributed plugin ships **any Composer runtime dependency** (`require`, not `require-dev`) — HTTP clients, SDKs, loggers, parsers. |
| 8 | - Two plugins **fatal or misbehave together** with "Cannot redeclare class", wrong-version method signatures, or `Uncaught Error: Call to undefined method` on a vendor class. |
| 9 | - `composer.json` contains `extra.strauss` or `extra.mozart` (reviewing or extending an existing setup). |
| 10 | - Migrating off **Mozart** (Strauss began as a Mozart fork and reads the Mozart config for a seamless migration). |
| 11 | - Setting up the release/CI build for a plugin whose `vendor/` is gitignored. |
| 12 | |
| 13 | ## Install: pinned phar via composer scripts (recommended) |
| 14 | |
| 15 | The upstream-recommended install is the **phar**, downloaded on demand and run from composer scripts — not `composer require --dev brianhenryie/strauss`. The phar keeps Strauss's own dependency tree (`composer/composer`, `symfony/console`, `nikic/php-parser`, `monolog`, …) out of your dev autoloader, where it could conflict with your own dev tools. |
| 16 | |
| 17 | Create `bin/` (with a `.gitkeep`), add `bin/strauss.phar` to `.gitignore`, then: |
| 18 | |
| 19 | ```json |
| 20 | "scripts": { |
| 21 | "prefix-namespaces": [ |
| 22 | "sh -c 'test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/latest/download/strauss.phar'", |
| 23 | "@php bin/strauss.phar", |
| 24 | "@composer dump-autoload" |
| 25 | ], |
| 26 | "post-install-cmd": [ |
| 27 | "@prefix-namespaces" |
| 28 | ], |
| 29 | "post-update-cmd": [ |
| 30 | "@prefix-namespaces" |
| 31 | ], |
| 32 | "post-autoload-dump": [ |
| 33 | "@php bin/strauss.phar include-autoloader" |
| 34 | ] |
| 35 | } |
| 36 | ``` |
| 37 | |
| 38 | Every `composer install` / `composer update` now regenerates the prefixed tree automatically — nobody has to remember a manual step. |
| 39 | |
| 40 | For **reproducible CI builds**, pin a release instead of `latest`: |
| 41 | |
| 42 | ``` |
| 43 | https://github.com/BrianHenryIE/strauss/releases/download/0.28.1/strauss.phar |
| 44 | ``` |
| 45 | |
| 46 | Strauss follows WordPress's PHP floor ("this project will not increase its minimum required PHP version ahead of WordPress"); it runs on PHP 7.4+. |
| 47 | |
| 48 | ## Configure (`composer.json` → `extra.strauss`) |
| 49 | |
| 50 | Strauss works zero-config — `namespace_prefix` and `classmap_prefix` are inferred from your `composer.json` `name`/`autoload`, and `packages` defaults to everything in `require`. Set them explicitly anyway so the prefix is deliberate: |
| 51 | |
| 52 | ```json |
| 53 | "extra": { |
| 54 | "strauss": { |
| 55 | "target_directory": "vendor-prefixed", |
| 56 | "namespace_prefix": "My_Plugin\\Vendor\\", |
| 57 | "classmap_prefix": "My_Plugin_Vendor_", |
| 58 | "constant_prefix": "MYPLUGIN_", |
| 59 | "packages": [], |
| 60 | "update_call_sites": false, |
| 61 | "delete_vendor_packages": false |
| 62 | } |
| 63 | } |
| 64 | ``` |
| 65 | |
| 66 | Key options and their defaults: |
| 67 | |
| 68 | | Option | Default | What it does | |
| 69 | |---|---|---| |
| 70 | | `target_directory` | `vendor-prefixed` | Where prefixed copies land. | |
| 71 | | `namespace_pr |