laminas/laminas-dependency-plugin
Composer plugin that eases migration from Zend Framework to Laminas by transparently replacing zendframework/* dependencies with their laminas/* equivalents during install and update, helping existing projects adopt Laminas without manual composer.json edits.
Minimal steps
composer require --dev laminas/laminas-dependency-plugin
Use require-dev for a normal app build, but keep it in require if your deployment pipeline runs composer update rather than composer install from a committed lock file.composer config allow-plugins.laminas/laminas-dependency-plugin true
(or set it in composer.json under config.allow-plugins).composer update and inspect the diff in composer.lock. Requirements on zendframework/* and zfcampus/* are rewritten to their laminas/* equivalents at dependency-resolution time.Where to look first
zendframework/foo → laminas/laminas-foo). This is the authoritative list of what will and won't be rewritten for your version.composer.lock diff after the first update — it is the clearest evidence of what the plugin actually did.composer why zendframework/... / composer why zfcampus/... to see which of your dependencies (or your own composer.json) still reference the old names.First use case
A legacy ZF2/ZF3 or zend-expressive application where your own composer.json and third-party dependencies still require zendframework/*. Add the plugin, run composer update, and let Composer resolve the Laminas equivalents before you touch any application code. This separates "get the dependency graph onto maintained packages" from "rename namespaces in src/", which are two very different jobs.
Migration sequencing
laminas-dependency-plugin and allow it.composer update until the lock file no longer contains zendframework/* or zfcampus/* (verify with grep -i zendframework composer.lock).laminas/laminas-migration (or manual edits) to rewrite Zend\* namespaces, config keys, and factory references in your code.composer update once more to confirm the graph is genuinely clean without the rewrite shim.Treat it as a transient compatibility shim
Keep the plugin only while the rewrite is needed. Its value is letting you upgrade dependencies before rewriting application code, and letting third-party packages that still require zendframework/* resolve correctly while you wait for upstream releases. Do not leave it in composer.json permanently — it hides residual Zend dependencies.
CI and Docker integration
allow-plugins into composer.json so CI never hits an interactive prompt.composer install from a committed lock file, the plugin is effectively a no-op — the lock is already resolved. The plugin only matters when the pool is built (update, require, remove). Ensure your build step that generates the lock also has the plugin available and allowed.composer update/require layer that needs the rewrite, and clear the Composer cache between attempts if substitution looks stale.Constraint handling
The plugin rewrites the package name in requirements but leaves the version constraint intact. Most Zend → Laminas equivalents share compatible version lines, but if a dependency pins an exact Zend version that has no corresponding Laminas release, resolution will fail rather than silently downgrade. In that case, override the constraint on the affected package in your root composer.json or file an upstream issue.
Extension points
The substitution map is the extension point. If your project has an in-house zendframework/* package or a fork with a nonstandard name, add it to the map (or provide a custom replacement through the plugin's configuration) so the rewriter covers it alongside the built-ins. Check the source for your installed version rather than assuming the README is current — this package has had a small, stable surface for years.
allow-plugins is the #1 trap. Without it, composer install/update either prompts (blocking CI) or refuses to run the plugin silently. Symptom: zendframework/* still in the lock despite the plugin being installed. Fix: composer config allow-plugins.laminas/laminas-dependency-plugin true.--no-plugins disables it. If you (or a wrapper script) run composer update --no-plugins, the rewrite never happens and you'll get confusing resolution errors or old packages. Audit CI flags.composer install against an existing lock will install exactly what's in the lock — Zend packages included. You must run update (or re-resolve the affected packages) to see the effect.Zend\Http\Client. Use laminas/laminas-migration for the code layer; expect a large diff and review it.composer update -vvv shows the pool being built and the rewritten requirements. composer why laminas/laminas-http and composer why zendframework/zend-http together tell you whether a rewrite took effect and who pulled the package in.composer clear-cache and re-run before assuming the plugin is broken.laminas/*, delete the plugin and re-run composer update --dry-run to confirm nothing falls back to Zend packages.composer.json to a known-good constraint, but don't expect frequent feature work — its job is intentionally narrow, and that's fine for a migration shim.How can I help you explore Laravel packages today?