Extension Composer Dependencies

Overview

Plugins and themes may declare PHP package dependencies. ValPress installs or verifies them on activation, blocks unsafe core updates when constraints conflict, and restores extension-managed packages after a core update.

Preferred packaging (recommended)

Ship a vendor/ directory (and composer.lock) inside the plugin or theme ZIP. ValPress loads vendor/autoload.php automatically when the extension boots.

This is the most reliable approach for non-technical sites: dependencies survive CMS updates even when Composer is not available on the host.

public/plugins/my-plugin/
├── config.php
├── plugin.php
├── composer.json
├── composer.lock
└── vendor/
    └── autoload.php

Declaring dependencies

config.php (primary)

return [
    'plugin_slug' => 'my-plugin',
    // ... required metadata ...
    'composer' => [
        'require' => [
            'guzzlehttp/guzzle' => '^7.8',
            'ramsey/uuid' => '^4.7',
        ],
    ],
];

Themes use the same composer.require key in their config.php.

Extension composer.json (optional)

If present, ValPress also reads the top-level "require" section (excluding php and ext-*). Values from config.php override duplicates.

Filter hook (advanced)

add_filter( 'valpress_extension_composer_require', function ( array $require, string $slug, string $directory ) {
    if ( $slug === 'my-plugin' ) {
        $require['guzzlehttp/guzzle'] = '^7.8';
    }

    return $require;
}, 10, 3 );

Per-slug filter: valpress_extension_composer_require_{slug}.

When ValPress installs packages

  1. Activate plugin/theme — requirements are checked; missing packages are installed into the CMS root via Composer when available.
  2. Core update finalize — active extension requirements are re-checked and reinstalled if a core update replaced vendor/.
  3. Extension update finalize — the updated extension’s requirements are ensured again.
  4. Repair action — Update Center repair id composer_ensure with type + slug.

If Composer is not available and the extension does not ship vendor/, activation fails with a clear error.

Uninstall / delete

When deleting a deactivated plugin or inactive theme from the admin UI, ValPress checks whether that extension contributed packages tracked in valpress_extension_composer_packages.

If it did, a confirmation dialog asks whether to:

  1. Delete the extension only (leave root Composer packages installed), or
  2. Also remove exclusive packages from the CMS root via composer remove

Removing packages is treated as a dangerous action: the admin must acknowledge that other plugins, themes, or custom code may still depend on those packages. ValPress will:

  • Never remove packages listed in the CMS root composer.json require
  • Keep packages still declared by other installed extensions
  • Only remove packages exclusive to the deleted extension when the admin opts in

Core update safety

During verification (extension_compat):

  • Constraints are checked against the upcoming composer.lock from the core update package when present.
  • Conflicts (core ships an incompatible version) block the update.
  • Missing packages (needed by extensions but not in the core lock) are:
    • Warnings when Composer is available (reinstalled after apply)
    • Failures when Composer is unavailable and no bundled vendor covers them

Scaffolding

php artisan vp:make-extension-composer plugin my-plugin
php artisan vp:make-extension-composer theme my-theme

Adds a composer.require stub to config.php when the key is not already present.

Marketplace

On ZIP upload (new product or version), the Marketplace extracts Composer requirements from:

  • Extension root composer.json"require"
  • And/or config.php'composer' => ['require' => [...]]

These are stored on each product version and shown on the editor review screen. The private API exposes composer_require (and compat_min) in version check responses so ValPress CMS can validate update safety.

If a declared constraint conflicts with a package version shipped by ValPress CMS (config/cms_composer_packages.php on the marketplace), the submission is soft-rejected automatically and cannot be auto-approved. Refresh that snapshot from the CMS repo after lockfile changes:

php artisan vp:export-cms-composer-packages path/to/market/config/cms_composer_packages.php

Recommended for Marketplace packages: ship a bundled vendor/ + composer.lock inside the ZIP so sites without Composer CLI still work.

Related docs