It's time to start testing Laminas migration!
The packages we are providing currently are not the final packages, and provided for testing purposes only. We are strictly looking for feedback on the migration process and its impact on your applications. Deploy at your own risk!
First off, huge kudos to Michał Bundyra (@michalbundyra and @webimpress on GitHub), for the huge amount of effort he has put into making this happen. Anything I throw at him, he has found a solution for, and the ability to migrate the repos would not be anywhere near where it is today without what he has done.
There are a few pieces to make it possible to do this testing, and I think it's important to know what they are.
-
I have taken all repositories we plan to migrate, and applied our rewrite tool to each tag and the HEAD commits of the master and develop branches ONLY. Since tarballs are only created for tagged releases, you cannot use
dev-(master|develop)
or*
constraints. -
From that, I have created a Composer repository at the URL https://laminas.mwop.net/repo/testing
-
We have created three userland tools to help facilitate migrations:
-
laminas/laminas-zendframework-bridge is a helper package that intercepts autoload requests for ZF classes and, if an equivalent Laminas class is present, autoloads that instead; additionally, it aliases the original ZF class to the Laminas version. This package is added to every Laminas package at every release currently, and is what allows them to be used as replacements, since the aliasing means that normal inheritance continues to work just as it did previously.
Additionally, it provides a configuration post processor that can be registered both with zend-config-aggregator (Expressive applications) or zend-modulemanager (MVC applications) for the purposes of rewriting known keys and values to their Laminas equivalents. This feature, when used, makes most third party libraries de facto forwards compatible with Laminas.
-
laminas/laminas-dependency-plugin is a Composer plugin that intercepts install and update operations. If a request for a ZF package is detected, it will slip-stream in the equivalent Laminas package instead. This is particularly of interest following a migration to ensure that nested dependencies on ZF packages use Laminas versions.
-
laminas/laminas-migration is a command line tool to facilitate migrating a project or third-party library to target Laminas. It will update the
composer.json
to target Laminas packages, and rewrite references to ZF classes and configuration throughout your application to the Laminas equivalents, add a dependency on laminas/laminas-dependency-plugin, and inject the configuration post processor provided by laminas/laminas-zendframework-bridge into your MVC or Expressive application if it can.
-
The migration tooling, as well as the dependency plugin and bridge package, requires PHP 5.6 and up.
While many of the package versions support previous PHP versions, we chose to support only versions supported either by PHP.net or commercially. The lowest supported version we could find was PHP 5.6. As such, you will need to update to at least that version of PHP before attempting a migration.
Ideally, we recommend upgrading to the latest stable version of PHP whenever possible.
Due to features of Composer our dependency plugin uses, we require Composer
1.7.0 and up. If you're unsure what version you are on, run composer --version
.
If you are on an older version, run composer self-update
.
To migrate a project, first install the laminas/laminas-migration package.
Install the library globally using Composer:
$ composer global require laminas/laminas-migration
If you choose this option, you will need to ensure that the vendor/bin/
subdirectory of your > global Composer installation is in your environment
$PATH
.
You can find where the global Composer installation is by executing:
$ composer global config home
On Linux and Mac operating systems, update your shell configuration to add
that path to your $PATH
environment variable.
The mechanism for adding to your environment
$PATH
variable depends on your operating system.For Linux, Mac, and other *nix variants, you can do so by adding a line like the following at the end of your profile configuration file (e.g.,
$HOME/.bashrc
,$HOME/.zshrc
,$HOME/.profile
, etc.):export PATH={path to add}:$PATHFor Windows, the situation is a bit more involved; this HOWTO provides a good tutorial on the subject.
Clone the repository somewhere:
$ git clone https://github.com/laminas/laminas-migration.git
Install dependencies:
$ cd laminas-migration
$ composer install
From there, either add the bin/
directory to your $PATH
(see the note on
adding to the PATH, above), symlink the
bin/laminas-migration
script to a directory in your $PATH
, or create an
alias to the bin/laminas-migration
script using your shell:
# Adding to PATH:
$ export PATH=/path/to/laminas-migration/bin:$PATH
# Symlinking to a directory in your PATH:
$ cd $HOME/bin && ln -s /path/to/laminas-migration/bin/laminas-migration .
# creating an alias:
$ alias laminas-migration=/path/to/laminas-migration/bin/laminas-migration
- Last updates: 2019-12-02
If you are not a first-time tester, and you last installed the migration tooling before the date listed above, you will need to upgrade your tooling in order to test.
Run the following commands:
$ composer global remove laminas/laminas-migration $ composer global require laminas/laminas-migrationRun the following commands:
$ cd path/to/laminas-migration $ git fetch origin $ git rebase origin/master # or checkout the latest tag: $ git checkout 0.2.0 $ composer install
From there, enter a project you wish to migrate, and run the following:
$ laminas-migration migrate
You may want to use the --exclude
or -e
option one or more times for
directories to exclude from the rewrite; on the ZF website and my own, I used
-e data
, for instance:
$ laminas-migration migrate -e data
If you are migrating an MVC, Apigility, or Expressive application, the migration tooling attempts to inject some code in your application. This can fail if you have non-standard configuration.
For MVC and Apigility applications, the migration tooling attempts to add
Laminas\ZendFrameworkBridge
as a module to the top of theconfig/modules.config.php
file. If injection fails, add the module in a way appropriate to your application.For Expressive applications, the migration tooling attempts to add
Laminas\ZendFrameworkBridge\ConfigPostProcessor
as a post processor class to theConfigAggregator
constructor. TheConfigAggregator
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 an Expressive application 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.
This step will go away once we migrate the repositories to their final resting places on GitHub. However, until then, we need to add the custom repository I created:
$ composer config repositories.laminas composer https://laminas.mwop.net/repo/testing
Once migration is done and you've added the repository, you can install dependencies:
$ composer install
Run your unit tests, do end-to-end tests, whatever — but exercise the application in some way, and let us know if anything does not work. The more specific you can be, the better!
Please report your experiences in the #laminas-migration-testing channel on the ZF Slack.
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-enableExpressive users can use the
clear-config-cache
command:$ composer clear-config-cache
To summarize the steps to test:
$ composer global require laminas/laminas-migration
$ cd some/project
$ laminas-migration migrate -e data
$ composer config repositories.laminas composer https://laminas.mwop.net/repo/testing
$ composer install
and report to the #laminas-migration-testing channel on the ZF Slack.
We want to hear ALL experiences, both if it worked and if it failed, as well as the type of application you tested migrations against. The more information we have about use cases, the more we know about how well the tool covers the various projects in the ecosystem.
Feel free to invite others to test!
Happy testing!
@shughi94 —
I've tried to reproduce your issue, but so far have not been able to. To reproduce, I did the following:
composer create-project
.ProblemDetailsExceptionInterface
and uses theCommonProblemDetailsExceptionTrait
to provide the bulk of implementation.PingHandler
to throw this exception.I then served the application and accessed the
/api/ping
URL.Both before and after migration, this returns an HTML page containing the exception stack trace. This is as expected; the shipped
ErrorHandler
middleware has no facilities for returning errors in any other format currently.When I modified the route for the
/api/ping
URL to be a middleware pipeline that includes theProblemDetailsMiddleware
, I received the hoped for JSON output - as I expected. And this was true both before and after migration.As such, I think perhaps you had a custom ErrorHandler middleware before...