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 Installer Laravel Package

cakephp/plugin-installer

Composer installer for CakePHP plugins that automatically places packages into the app's plugins directory. It simplifies plugin dependency management and removes manual copying, helping CakePHP projects install and organize plugins consistently.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package — it is a Composer installer plugin for CakePHP. It exists for exactly one job: when a dependency declares "type": "cakephp-plugin", this plugin installs it into the application's plugins/ directory instead of vendor/. In a pure Laravel codebase you will never add it deliberately; you'll only meet it inside the dependency tree of a CakePHP project (or a package that still requires it).

  1. Confirm you actually need it. Run composer why cakephp/plugin-installer. If nothing in your tree is a cakephp-plugin, remove it. If you're on a CakePHP app, it is usually already pulled in by cakephp/cakephp or the cakephp/app skeleton.

  2. Allow the plugin (Composer 2.2+). Composer will refuse to run third-party plugins until they are allow-listed. Either answer y at the prompt, or commit this in the root composer.json so CI works:

    {
      "config": {
        "allow-plugins": {
          "cakephp/plugin-installer": true
        }
      }
    }
    
  3. Look at these files first.

    • vendor/cakephp/plugin-installer/composer.json — note "type": "composer-plugin" and "extra": { "class": "Cake\\Composer\\Installer\\PluginInstaller" }.
    • vendor/cakephp/plugin-installer/src/PluginInstaller.php — it implements Composer\Installer\InstallerInterface, supports() returns true for cakephp-plugin, and getInstallPath() decides where files land.
    • Your app's root composer.json — the extra block is where the target path is configured.
  4. First use case. In a CakePHP app:

    composer require somevendor/my-plugin
    

    Instead of vendor/somevendor/my-plugin, you should see plugins/MyPlugin/ (or plugins/SomeVendor/MyPlugin, depending on package name). Then, in CakePHP, bin/cake plugin load MyPlugin. If the files land in vendor/ instead, the plugin is not being loaded — go straight to the Gotchas section.

  5. First use case for a Laravel dev specifically. You are much more likely to read this package as a reference implementation of the Composer plugin API than to install it. It is a compact, ~100-line example of PluginInterface + InstallerInterface that you can copy if you ever need to ship something outside vendor/ (theme packages, first-party app modules, deploy-time scaffolding).

Implementation Patterns

Zero-config transitive use. Most of the time you do nothing. The plugin is registered by Composer from the dependency's own composer.json, and any subsequent cakephp-plugin package is routed to plugins/. Your only obligation is the allow-plugins entry.

Explicit root-level requirement. If you are pinning the installer for reproducibility:

{
  "require-dev": {
    "cakephp/plugin-installer": "^2.0"
  },
  "config": {
    "allow-plugins": {
      "cakephp/plugin-installer": true
    }
  }
}

Keeping it in require-dev is fine when only your own plugins (not transitive dependencies) need it; but if a runtime dependency is a cakephp-plugin, it must be in require or Composer may install it before the plugin is active.

Authoring a plugin package. If you publish a package meant to be dropped into plugins/, set the type and keep autoload paths relative to the package root — Composer rewrites them against the real install location automatically:

{
  "name": "acme/cakephp-audit",
  "type": "cakephp-plugin",
  "autoload": {
    "psr-4": { "Acme\\Audit\\": "src/" }
  },
  "require": {
    "cakephp/cakephp": "^5.0"
  }
}

Monorepo / multiple apps. In a repository hosting several CakePHP apps, each app's root composer.json owns its own plugins/ path. Because the installer resolves relative to the root package, running composer install from a subdirectory still targets that subdirectory's plugins/. Keep one composer.lock per app.

Local development with path repositories. This is the pattern you will actually use day-to-day while building a plugin:

{
  "repositories": [
    { "type": "path", "url": "../cakephp-audit", "options": { "symlink": true } }
  ],
  "require": { "acme/cakephp-audit": "*" }
}

The symlink points at plugins/Audit, so edits are live. Note the symlink target is the plugin dir, not vendor/ — IDE indexing and file watchers need to be told about plugins/.

CI and container builds. Bake the allow-list into composer.json and never rely on the interactive prompt:

COPY composer.json composer.lock ./
RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader

If you cache vendor/ between CI runs, also cache plugins/ — otherwise you get a half-installed tree (autoload files referencing plugin classes that were never written).

Adapting the pattern to Laravel. Laravel has no equivalent and does not need one: packages are library type, stay in vendor/, and register themselves via extra.laravel.providers package discovery. The only time to reach for a custom installer in Laravel is when files must be mutable at runtime outside vendor — and even then, a publishable config/asset (php artisan vendor:publish) is almost always the better answer.

Gotchas and Tips

  • --no-plugins silently breaks the layout. composer install --no-plugins, --no-scripts, or COMPOSER_NO_PLUGINS=1 disables installers, so every cakephp-plugin lands in vendor/ and the app cannot find it. This is the single most common failure, and it is silent — no error, just a missing plugins/ directory.

  • The Composer 2.2 allow-list prompt kills non-interactive builds. In CI you get Plugin ... could not be loaded or a hard failure. Commit config.allow-plugins rather than answering the prompt locally and forgetting it.

  • The lock file does not record the install path. It records the package and version only. If you change the plugin path, composer install will happily reuse the existing installed tree and not move anything. Force it:

    rm -rf vendor plugins composer.lock && composer install
    
  • Competing installers. composer/installers with an installer-paths rule that claims type:cakephp-plugin, or oomphinc/composer-installers-extender, will win or lose depending on plugin registration order. Symptoms: packages intermittently in vendor/ instead of plugins/. Inspect with composer install -vvv and check vendor/composer/installed.json for the install-path field on the affected package.

  • Autoloading still works — but only through Composer. Composer generates the autoloader from the actual install path, so PSR-4 classes resolve fine even outside vendor/. What breaks is everything that assumes vendor/: PHPStan/Psalm paths, phpcs file lists, COPY vendor/ in a Dockerfile, .gitignore rules, and composer audit/SBOM tooling that only walks vendor/. Audit those configs when you adopt it.

  • plugins/ is usually git-ignored but is not reproducible from vendor/ alone. A deploy that ships vendor/ as an artifact must also ship plugins/, or run composer install on the target.

  • type casing and name matching. The installer supports the exact type string cakephp-plugin. A typo (cakephp-plugins) drops the package into vendor/ with no warning.

  • Debugging checklist: composer diagnose → composer install -vvv 2>&1 | grep -i -E 'install|plugin' → composer show -t to confirm the plugin is in the tree → cat vendor/composer/installed.json | grep install-path.

  • Extension point. If you need a different destination (e.g. per-vendor subdirectories, or a custom root), the only supported lever is the root composer.json extra configuration documented in the README. Anything more requires forking PluginInstaller::getInstallPath() — the class is tiny and self-contained, so a fork is genuinely low-risk if you must.

  • Project health caveat. Very low star count, no dependents reported, and infrequent releases. Treat it as a load-bearing-but-unmaintained piece of the CakePHP skeleton: pin the major version in composer.json, and do not adopt it for new architecture in a Laravel/other-framework codebase. If you want the behavior, copy the ~100-line installer into your own composer-plugin package where you control the maintenance.

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