A few Notes about Migrating to Laminas

In 2019 I wrote about a MySQL 5.7 migration at Check24. While it is very exciting when working on new features, it is also a good thing to think about the architecture and use modern frameworks and libraries. Working on the architecture provides also the opportunity to improve source code quality and introduce quick wins.

The following notes are part of my recent project at Check24. I am a bit proud about it, since it was initiated, designed and pushed by me. Although some requirements were already fulfilled, I had to migrate code from our old code base, make it PSR-ready (PSR-4, PSR-7 and PSR-11) and ensure that everything works as before.

For those who do not know Laminas: it was previously known as the Zend Framework. Laminas is now part of the Linux foundation. Besides to Laminas MVC (previously Zend MVC) there is the Laminas Mezzio (previously Zend Expressive).

Module Structure

I believe in flat, modular and loosely coupled source code. Bundling code, tests and all other artifacts to a module makes it easier to search, share and reuse code. Further, if someone wants to exclude code to a library or just wants to remove the feature he/she has only to remove the module. Cross-dependencies between modules should be minimized to a minimum but are ok, as long as they utilize interfaces or PSR standards.

Routing & Middleware

Using the Laminas Router, you can register global or route specific middleware. For instance, if you want to secure your routes with HTTP Basic Authentication, you can simply write (or use) a global middleware. There is also the way to register route specific middleware, for instance when you have repeating parameters that need to be validated before they reach the endpoint.

Guzzle HTTP and Authentication

Guzzle Configuration, such as HTTP Basic Auth and SSL verification, is injected via constructor. That’s why we needed to build the client on runtime and no service factory could be utilized. The Builder Pattern can help here: just create an “ClientBuilder” that provide some configuration methods to configure the Guzzle Client and build on runtime. Ideally the builder returns an instance of PSR ClientInterface, which makes it easy to exchange later if needed.


Not really a Laminas related topic, but important enough: caching. Caching is an important topic for almost every layer scaling applications. Whenever it is possible to save computation power, it should be perceived. And so with Laminas.

Laminas ConfigProvider or Module classes are used to provide configuration, such as services and their factory, routes, and so on. The application iterates every time over all ConfigProviders and generates the configuration which is usually a big key-value pair.

Especially on production, there is no need to iterate the ConfigProviders repeatedly. The Laminas Config Aggregator library, that is iterating the ConfigProviders, supports caching. Just need to configure a few options and the application saves computation power.

Parameter Encoding

Both, Guzzle on sender side and Laminas on receiver side support different Content-Type header. I have faced the issue that some services consumed endpoints with the application/x-www-form-urlencoded Content-Type, which caused issues on the endpoint side. Simply putting the JSON request option on Guzzle fixed this issue.

Some Issues with with requests and responses

Again, Guzzle as well as Laminas, support PSR-7 HTTP Message Interface. You should be aware of the difference $response->getBody() and $response->getBody()->getContents(). Where the former returns an StreamInterface and can be casted to string in order to process the API response, the later points to the stream and can point to the end which will result in an empty string. $response->getBody()->rewind() will rewind to the beginning of the stream.


I like helping code bases to migrate to proven standards and refactor code. Reusability and code shrinking by utilizing software patterns and concepts (such as Dependency Injection or the good old Builder Pattern) make a huge difference and a lot of things easier.

There is also a lot of things to learn for me and thus, we profit both: Check24 and me. Stay tuned, I will continue contributing to “Deutschlands größtem Vergleichsportal”…