On this page
FAQ
Removing the PHP Memory Limit When Migrating
In some cases when running the migration tooling, you may run into a fatal
error indicating the PHP memory_limit
has been reached.
To resolve this, you will need to run the laminas-migration
tool through the PHP interpreter.
First, determine where the script lives:
$ which laminas-migration
Next, when invoking the command, invoke it as follows:
$ php -d memory_limit=-1 path/to/bin/laminas-migration # and any arguments you need
This will disable the memory limit, which should allow your script to finish successfully.
Module and Config Post Processor injection
If you are migrating an MVC, Apigility, or Expressive application to Laminas, the migration tooling attempts to inject some code in your application. This can fail if you have non-standard configuration.
Migrating MVC and Apigility applications
When migrating MVC and Apigility applications to Laminas MVC and Laminas API
Tools, the migration tooling attempts to add Laminas\ZendFrameworkBridge
as a
module to the top of the config/modules.config.php
file. If injection fails,
add the module in a way appropriate to your application.
Expressive
When migrating Expressive applications to Mezzio, the migration tooling attempts
to add Laminas\ZendFrameworkBridge\ConfigPostProcessor
as a post processor
class to the ConfigAggregator
constructor. The ConfigAggregator
constructor
has the following signature:
public function __construct(
array $providers = [],
?string $cachedConfigFile = null,
array $postProcessors = []
)
Typically, the structure of the config/config.php
file in Expressive and
Mezzio applications looks like the following:
$cacheConfig = [
'config_cache_path' => 'data/cache/app_config.php',
];
$aggregator = new ConfigAggregator([
// config providers from 3rd party code
// ...
// App-specific modules
// ...
// Include cache configuration
new ArrayProvider($cacheConfig),
// Load application config in a pre-defined order in such a way that local settings
// overwrite global settings. (Loaded as first to last):
// - `global.php`
// - `*.global.php`
// - `local.php`
// - `*.local.php`
new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
// Load development config if it exists
new PhpFileProvider('config/development.config.php'),
], $cacheConfig['config_cache_path']);
return $aggregator->getMergedConfig();
As such, the migration tooling rewrites the second to last line to read:
], $cacheConfig['config_cache_path'], [\Laminas\ZendFrameworkBridge\ConfigPostProcessor::class]);
In most cases, failure to inject means that the individual arguments have been pushed to their own line. In such cases, add the third argument as detailed above.
In other cases, applications may already be using post processors. If so,
add \Laminas\ZendFrameworkBridge\ConfigPostProcessor::class
to the list of
post processors.
Alias Rewrites and 3rd Party Packages
While we have made huge efforts to prevent the migration tooling from clobbering your own code, there is two scenarios where we often cannot avoid it: when importing a namespace, and then referencing a class via that namespace; and when using 3rd party packages that reference legacy names.
As an example of the first scenario, consider the following usage of a class from the zendframework/zend-expressive-authorization-acl package:
use Zend\Expressive\Authorization\Acl;
// And later:
$acl = new Acl\ZendAcl();
The code above imports the Zend\Expressive\Authorization\Acl
namespace, and then later instantiates a class relative to that namespace.
Migration will rewrite this to:
use Mezzio\Authorization\Acl;
// And later:
$acl = new Acl\ZendAcl();
The latter line is incorrect at this point; it should read new
Acl\LaminasAcl();
. You will need to check for such scenarios either
via your test suite, or manually. The grep
tool or your IDE's "find" functionality can help you identify these; search
for "Zend" in your codebase after a migration).
For the second scenario, sometimes 3rd party packages use the term "Zend", "ZF", "Apigility", or "Expressive" in their namespaces or class names:
use Some\Vendor\ZendAcl;
// And later:
$acl = new ZendAcl();
In the above example, a class name from a 3rd party package contains the word "Zend" in it. After migration, this becomes:
use Some\Vendor\ZendAcl;
// And later:
$acl = new LaminasAcl();
The above is now incorrect, as it's referring to a class that is not imported and thus does not exist. These sorts of changes are harder to locate. Make sure you review your diffs closely, and that you have an adequate test suite, to ensure that the code is exercised; this is the best way to ensure you can catch these changes.
Clear your caches
If your application is not running in development mode, you will need to clear any configuration caches you have before testing. If you are using zf-development-mode (which becomes laminas-development-mode!), try enabling development mode:
$ composer development-enable
Expressive/Mezzio users can use the clear-config-cache
command:
$ composer clear-config-cache
Migrating With A zendframework/zendframework Package
If you have chosen to install the package zendframework/zendframework in your application, or if you started your project from the skeleton application before the 3.0 release, you will have some extra steps post-migration.
First, please make sure you use version 1.2.0 or later of laminas-migration. That version provides some important updates that ensure that your zendframework/zendframework package is migrated to the correct Laminas packages.
Afterwards, we recommend that you remove any packages you are not explicitly using from your project, per the following steps.
Identify Packages You Use
The first step is to identify which individual packages you actually consume.
From a *nix or Mac command-line, you can run code similar to the following to get a list of uniquely imported classes:
$ grep -rP 'use Laminas' {source code directories} | uniq | sort
Where {source code directories}
can be one or more of src/
,
modules/
, config/
, bin/
,
public/
etc., but NOT vendor/
. You will want to
ensure every such directory is listed. If you are using an IDE, you may be
able to do a project-wide search.
The above will provide a list of namespaces and classes that you are importing in your project. From there, you can match those namespaces to the appropriate package. As examples:
Laminas\Mvc\Controller\AbstractController
would translate to the laminas/laminas-mvc package.Laminas\Form\Form
would translate to the laminas/laminas-form package.Laminas\Navigation\Page\Mvc
would translate to the laminas/laminas-navigation package.Laminas\ApiTools\ContentNegotiation\JsonModel
would translate to the laminas-api-tools/api-tools-content-negotiation package.- And so on.
Remove Old Dependencies
Once you have your list of packages that you use, do the following: your application:
- Open your
composer.json
file, and look for any entries related to Laminas packages, and make a list of any Laminas packages that are not in the list you compiled in the previous step. - Run
composer remove {package}
for each of these packages.
Once done, commit your composer.json
and
composer.lock
file.
Zend Framework v1 Considerations
Zend Framework version 1 is past end of life, so it does not receive any rewrites during migration. However, custom code in the project being migrated does receive rewrites. This has the potential to cause errors.
Zend_Mail
The Zend_Mail
component uses a "ZendMail_" prefix for filenames generated by the Zend_Mail_Transport_File
transport. After migration, this transport adapter will continue to generate filenames using the "ZendMail_" prefix. Any custom code that also references the "ZendMail_" prefix will be rewritten to instead use a prefix of "LaminasMail_".
Since the v1 Zend_Mail
component and later versions both use the same "ZendMail_" prefix, the migration cannot discriminate when rewriting custom project code. Consequently, you will need to reconcile any errors in your code arising from this prefix rewrite.