The official Laminas migration tool (laminas/laminas-migration) does the bulk of the namespace conversion from Zend\ to Laminas\. It rewrites PHP files, configuration arrays, and Composer dependencies. For many applications, running the tool gets you 80% of the way there in under an hour. The remaining 20% is the part that trips people up, and that is what this guide focuses on.
This guide is a companion to the Zend to Laminas Migration Checklist, which covers the full process end to end. Here we drill into the migration tool itself: what it does, what it does not do, and how to fix the gaps.
Running the Migration Tool
Install the tool globally:
1 | composer global require laminas/laminas-migration |
Then run it against your project root:
1 | laminas-migration migrate /path/to/your/project |
The tool processes:
- PHP files: rewrites
Zend\namespaces toLaminas\andZendService\toLaminasService\ - Configuration files: converts factory and service names in
.phpand.config.phpfiles - Composer dependencies: replaces
zendframework/*packages with theirlaminas/*equivalents - Some documentation files: updates references in
.mdfiles
What Happens During the Run
The tool creates a backup of modified files before changing them. It uses regex-based string replacement rather than AST parsing, which means it is fast but can be overzealous in certain contexts.
Expect the run to take between 30 seconds and 5 minutes depending on project size. On a typical Laminas MVC application with 200 to 500 PHP files, it completes in under a minute.
After the tool finishes, run composer update to pull in the Laminas packages that replaced the Zend packages. This is where the first round of real problems tends to surface.
What the Tool Gets Right
The migration tool handles these conversions reliably:
Namespace use statements. Every use Zend\... becomes use Laminas\.... This covers imports, type hints, instanceof checks, and class name references in PHP code.
Fully qualified class names. \Zend\Mvc\Application::init() becomes \Laminas\Mvc\Application::init(). The tool catches both the leading backslash and non-backslash forms.
Composer dependency names. zendframework/zend-mvc becomes laminas/laminas-mvc. The mapping is maintained in the tool’s source and covers all official packages.
Configuration keys that are class names. In service manager configuration arrays, factory class names like 'Zend\Db\Adapter\Adapter' are rewritten to 'Laminas\Db\Adapter\Adapter'.
What the Tool Misses
Here is where you spend the other 80% of your time.
String References in Configuration
The tool rewrites class name strings it recognises, but it does not catch every string pattern. Configuration values that reference Zend packages by convention rather than by class name are often missed:
1 | // MISSED: the tool may not recognise this as a namespace reference |
Search for remaining Zend references after running the tool:
1 | grep -rn 'Zend' application/ config/ module/ --include='*.php' --include='*.config.php' --include='*.ini' |
Review every match. Some will be legitimate (comments, documentation, variable names that happen to contain “Zend”), but many will be missed conversions.
Factory Class References in Configuration Arrays
Service manager, controller manager, view helper manager, and input filter manager configurations all reference factory classes. The tool converts the class names but does not always handle aliased keys:
1 | // Before |
Check all aliases, invokables, abstract_factories, and delegators arrays manually.
INI Configuration Files
If your application uses .ini configuration files (common in ZF1-to-Laminas bridges), the tool may not process them:
1 | ; application.ini - these references may survive the migration tool |
The resource keys themselves do not change (they are not namespaced), but if you have custom resource plugins that reference Zend classes in their configuration, those need manual updating.
View Scripts with Hardcoded Class Names
View helpers in .phtml files sometimes reference Zend classes directly:
1 |
|
Check that the tool was configured to process .phtml files. If not, scan them separately:
1 | grep -rn 'Zend' application/views/ --include='*.phtml' |
Database Content
If your application stores class names in the database (serialized objects, job queue payloads, cached data), those references survive the migration tool entirely. You need a database migration script:
1 | -- Update serialized class references in session storage |
Be extremely careful with this. Test on a database copy first. Serialized PHP data has length prefixes that break if you change string lengths without updating the serialization metadata.
Third-Party Modules
If your application uses community ZF modules (ZfcUser, BjyAuthorize, DoctrineORMModule, etc.), many of these have Laminas-compatible forks but the package names changed. The migration tool may not know about community package mappings.
Check each third-party dependency individually:
- Is there a Laminas-compatible version?
- Has the package name changed?
- Does it require any configuration changes beyond the namespace swap?
Post-Migration Verification
After running the tool and fixing the manual items, run this verification sequence:
1. Composer Validation
1 | composer validate |
All packages should resolve without conflicts. If Composer reports version conflicts, you have a dependency that still references a Zend package.
2. Static Analysis Scan
If you use PHPStan or Psalm:
1 | vendor/bin/phpstan analyse |
Class-not-found errors indicate missed namespace conversions. Undefined method or property errors may indicate API changes between Zend and Laminas versions.
3. Grep for Remaining Zend References
1 | grep -rn 'Zend\\' application/ config/ module/ src/ --include='*.php' | grep -v 'vendor/' | grep -v '.git/' |
Every match needs evaluation. Not all are problems (some may be in comments or comparison strings), but each should be checked.
4. Test Suite
Run your full test suite. Failures fall into three categories:
- Class not found: missed namespace conversion
- Method not found: API change between Zend and Laminas versions
- Behaviour change: subtle differences in how Laminas components handle edge cases compared to their Zend predecessors
5. Manual Smoke Test
Log in. Submit forms. Check every page type. Look at error logs. Some issues only manifest at runtime, particularly those related to configuration loading, service resolution, and view rendering.
Tips for Large Codebases
Run the tool on a fresh branch. Review the diff before merging. Git’s diff view makes it easy to spot incorrect replacements.
Process in stages. If your application has multiple modules, migrate one module at a time. Get it passing tests before moving to the next.
Use the polyfill packages. Laminas provides laminas/laminas-zendframework-bridge which creates class aliases from old Zend names to new Laminas names. This lets you migrate incrementally rather than all at once:
1 | composer require laminas/laminas-zendframework-bridge |
The bridge means unconverted references still resolve. Remove the bridge once all references are converted.
Keep a list of manual fixes. When you find something the tool missed, document the pattern. After the migration, this list becomes your verification checklist for any modules you migrate later.
FAQ
Can I run the tool multiple times?
Yes, but subsequent runs will attempt to convert already-converted references, which is a no-op. The tool is idempotent for most conversions.
Does the tool handle ZF1 underscore-style class names?
No. If you are migrating from ZF1 (Zend_Controller_Action) rather than ZF2/ZF3 (Zend\Mvc\Controller\AbstractActionController), the tool does not apply. You need a different migration path.
What about the ZF3 to Laminas transition specifically?
ZF3 to Laminas is what the tool is designed for. It handles the namespace mapping for all official ZF3 components.
Next Steps
Run the tool, fix what it misses using this guide, and verify with the test suite. The Zend to Laminas Migration Checklist covers the full migration process including configuration changes, testing adjustments, and deployment considerations.
For the architectural context of how these namespaces map to the application structure, the Architecture of Zend Framework Applications chapter explains the module system and service manager patterns that both Zend and Laminas share.