Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Plugin Infrastructure Laravel Package

johnbillion/plugin-infrastructure

Reusable infrastructure for WordPress plugins: a set of classes and utilities covering common plugin needs such as hooks, admin settings, and lifecycle handling, helping developers build cleaner, more maintainable plugins with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

What this actually is: a Composer package of shared, opinionated dev tooling for John Blackbourn's WordPress plugins — test bootstrapping, coding-standard configs, static analysis and build/deploy scaffolding. It is not a runtime library and it is not a general-purpose WP framework. You adopt it to inherit one maintainer's conventions wholesale, then override the small parts that differ per plugin.

Minimal steps:

  1. Add it as a dev dependency only:
{
  "require-dev": {
    "johnbillion/plugin-infrastructure": "^1.0"
  },
  "config": {
    "allow-plugins": {
      "dealerdirect/phpcodesniffer-composer-installer": true
    }
  }
}
  1. Run composer install, then read vendor/johnbillion/plugin-infrastructure/README.md first — it is the only authoritative description of the current file layout. Then inspect the shipped config files (PHPCS ruleset, PHPUnit config, any Psalm/static-analysis config) and the bin/ scripts. Those files, not the PHP source, are the real public API of this package.

  2. First use case: wire up linting. Point your plugin's phpcs.xml.dist at the package ruleset, then run vendor/bin/phpcs. It is the lowest-risk, highest-immediate-value entry point:

<?xml version="1.0"?>
<ruleset name="My Plugin">
    <rule ref="./vendor/johnbillion/plugin-infrastructure/phpcs.xml.dist"/>
    <file>./src</file>
    <file>./my-plugin.php</file>
</ruleset>

Where to look first: README.md → shipped config files → bin/ scripts → src/ class (usually a small helper/constant holder). The src/ code is the least interesting part; the configs and scripts are where the day-to-day value lives.

Implementation Patterns

1. Inherit configs by reference, don't copy them. The whole point is that upstream fixes (new WPCS sniffs, PHPUnit polyfills, CI tweaks) arrive via composer update. Copy-paste the config once and you have forked the infrastructure permanently.

<!-- phpcs.xml.dist: extend, then narrow -->
<rule ref="./vendor/johnbillion/plugin-infrastructure/phpcs.xml.dist"/>
<exclude-pattern>./vendor/*</exclude-pattern>
<rule ref="WordPress.WP.I18n">
    <properties>
        <property name="text_domain" value="my-plugin"/>
    </properties>
</rule>

2. Reuse the PHPUnit bootstrap instead of writing your own. The package exists largely so the WP test-suite bootstrap isn't rewritten for every plugin. In your phpunit.xml.dist, point bootstrap at the package's bootstrap and supply the environment it expects:

<phpunit bootstrap="./vendor/johnbillion/plugin-infrastructure/tests/bootstrap.php">
    <testsuites>
        <testsuite name="unit">
            <directory>./tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

The bootstrap will look for a WordPress test install — set WP_TESTS_DIR (or WP_DEVELOP_DIR) in your local shell and in CI. Locally: bin/install-wp-tests.sh from wp-phpunit/wordpress-develop.

3. Make Composer scripts your single task runner. This is how the infrastructure becomes day-to-day rather than ceremony:

{
  "scripts": {
    "lint": "phpcs",
    "lint:fix": "phpcbf",
    "test": "phpunit",
    "test:coverage": "phpunit --coverage-html build/coverage",
    "check": ["@lint", "@test"]
  }
}

Then composer check locally and in CI is one command, and the definition lives in the repo, not in a YAML file nobody reads.

4. Mirror the package's CI shape. Reuse whatever workflow fragments it ships (or the patterns its README documents): a PHP-version × WP-version matrix, MySQL service container, composer install, composer check. Keep the matrix in your own .github/workflows/ but keep the commands identical to your local scripts so CI failures reproduce locally.

5. Override per plugin rather than fork. Every project needs different exclusions, prefix rules, text domains, minimum PHP and WP versions. Express all of that in your own thin config layer that references the package. Rule of thumb: your plugin's infra files should be 10–40 lines, not 300.

6. Build/deploy as a separate concern. For release artifacts, do a clean composer install --no-dev --optimize-autoloader in a staging copy, rsync excluding dev files, and zip. Never let the dev infrastructure end up in the distributed plugin. If the package ships a build script, call it from a composer build alias so contributors don't need tribal knowledge.

7. Keep it current deliberately. Add Renovate/Dependabot for johnbillion/plugin-infrastructure, but review bumps as potentially behavioral: a WPCS or PHPUnit bump changes your lint/test results without a line of your code changing.

Gotchas and Tips

  • It must live in require-dev. The most common mistake is adding it to require, which drags dev tooling into production autoload and inflates the plugin zip. If you see it in vendor/ of a shipped plugin, that's a bug.
  • This is one person's opinions, versioned. Low stars and zero dependents mean sparse docs and no external compatibility pressure. Pin a version range, actually read the diff on upgrades, and expect config files to move or change semantics between releases. There is no meaningful semver promise for "the ruleset got stricter."
  • PHPUnit ↔ WP test suite ↔ PHP version triad. Most failures are mismatches here, not in your code. Symptoms: Call to undefined method from the polyfills, bootstrap dying on a missing WP_TESTS_DIR, or tests silently skipped. Check the package README for the PHPUnit major it targets before upgrading your test runner.
  • Local DB requirement. The integration bootstrap needs MySQL/MariaDB and the WP test library installed. If composer test works in CI but not locally, that's almost always the missing test install, not the package.
  • Relative paths resolve from the config file's own directory. When referencing the vendor config, use ./vendor/... from the project root, and be wary of __DIR__ in copied snippets — it now points into vendor/ and will silently include the wrong files.
  • PHPCS standard registration. If phpcs -i doesn't list the standards you expect, the composer installer plugin wasn't allowed (see the allow-plugins snippet) or vendor/bin/phpcs is resolving a global install. Run vendor/bin/phpcs -s to see sniff names in output, and -vvv when a ruleset ref fails to load.
  • Don't edit vendor/. Any tweak you make there disappears on the next composer update. If you need different behavior, add your own config layer upstream of the package's.
  • Extension points are the configs, not the class. If you find yourself wanting to subclass or hook the package's PHP code, you're using the wrong tool — write the 20 lines yourself.
  • Debugging order: composer show johnbillion/plugin-infrastructure (confirm version) → read the matching README.md in vendor/ → run the underlying binary directly (vendor/bin/phpunit --debug, vendor/bin/phpcs -vvv) rather than through Composer scripts, so exit codes and output aren't swallowed.
  • Good fit: a portfolio of WP plugins by a small team that wants uniform standards and cheap CI. Poor fit: a single plugin with an existing toolchain, or a team that needs documented, supported, general-purpose scaffolding — the cost of conforming to someone else's conventions will exceed the setup you save.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core