How to Begin Migrating From Zend Framework 2 to Zend Expressive

If you are managing one or more Zend Framework 2 applications, did you know that you can already begin porting them to Zend Expressive? In this tutorial, you will learn how you can start today, using the Zend/PSR-7 bridge.


How to Migrate From Zend Framework 2 to Zend Expressive

If you are managing one or more Zend Framework 2 applications, did you know that you can already begin porting them to Zend Expressive? In this tutorial, you will learn how you can start doing so today, using the Zend/PSR-7 bridge.

A Little Background

Zend Framework is one of the most venerable frameworks in PHP — I like to think that it’s one of its best. But since Zend Expressive’s come along, it’s fair to say that it no longer is.

With Zend Expressive, you get access to the vast array of Zend Framework libraries and components, yet without the overhead of the MVC.

Additionally, by making use of PSR7 and Middleware, applications can be built in very unique and specific ways; something not possible using Zend MVC.

So, what do you do if you have to manage one or more legacy applications, written in Zend Framework 2? What do you do if you began building your organization’s next application using Zend Framework 2, yet believe that Zend Expressive’s a better choice?

Starting From Scratch Is Seldom a Good Idea

At times like these, you might feel that starting over from scratch is the right choice. But, according to most research on the subject, more often than not, starting over from scratch is both more expensive, and usually results in projects which are abandoned before they’re ever launched.

I’m not just praising the work of Paul M. Jones, Adam Culp, Martin Fowler, and others. It’s something I’ve personally experienced in several projects. Without going in to too much detail, rewriting from scratch is more expensive because:

  • You have to maintain the existing application whilst developing the next version
  • Existing developers need to divide their time between supporting the old version and developing the new version
  • Features added to the old version need to be added to the new version

And that’s just the tip of the iceberg. As a result, it’s often far more cost effective, far more practical — even if it doesn’t seem so — to refactor instead of rewrite.

That’s why I’m taking you through a four-step refactoring process, using the Zend/PSR7-Bridge, to begin porting your existing Zend Framework 2 application(s) to Zend Expressive.

Specifically, in this tutorial you’re going to learn how to refactor a Zend Framework 2 Controller to a Zend Expressive middleware class.

Installing The PSR7-Bridge

But before we begin, we have to install the library. To do so, assuming that Composer’s available in your system path, run the following command, in the terminal, from the root directory of your project:

composer require zendframework/zend-psr7bridge;

With that done, we’re ready to begin.

Step One - Create The Middleware Class

Let’s assume that you have an MVC Controller class which renders a standard business page, i.e., a terms and conditions, disclaimer, or privacy policy. Let’s see how to create a piece of PSR7 middleware to render it instead.

Firstly, in your existing directory structure which, for the purposes of this tutorial, will be module\Application\src\. In there, create a new directory called Middleware, and in it create a new class called DisclaimerPageMiddleware.php. In it, add the following code:

class DisclaimerPageMiddleware
{
    private $viewManager;
    private $viewRenderer;

    public function __construct($viewRenderer, $viewManager)
    {
        $this->viewRenderer = $viewRenderer;
        $this->viewManager = $viewManager;
    }

    public function __invoke($request, $response)
    {
        $viewModel = (new ViewModel())
                        ->setTemplate('your/view/template');
        $layout = ($this->viewManager->getViewModel())
            ->setVariable(
                'content',
                $this->viewRenderer->render($viewModel)
            );

        return new HtmlResponse(
            $this->viewRenderer->render($layout)
        );
    }
}

To render a page template, the class needs access to two member variables, because it has needs access to the view layer. So, the class’ constructor will require both as dependencies, and initialize two private member variables the constructor dependencies.

The __invoke magic method is where all the action happens. There, we instantiate a new ViewModel object, which is the equivalent of how HTML views are rendered in Zend Framework.

On it, we set the path to the template to render, just as we would in Zend Framework 2, passing the template file’s name without the suffix, to the setTemplate() method.

After that, we initialize the layout, so that we have a two-step view. To do that, we get access to the ViewManager’s ViewModel object, by calling its getViewModel() method.

Then we set what will be rendered in the page action, by setting one variable, content. We set its value to be the result of rendering the template which we supplied to the setTemplate method.

With that completed, we then return a new HtmlResponse object, passing to it the result of rendering the page, which contains both the surrounding layout, and page action content. With that done, the code to render the output is completed.

Step Two - Initialize the Middleware

Next, we have to provide a way of instantiating the middleware we just created. To do that, we’re going to follow the factory convention commonly used in Zend Expressive applications created with the Zend Skeleton Installer.

Given that, in module\Application\src\Middleware create a new class, called DisclaimerPageMiddlewareFactory.php which contains the following code:

use Interop\Container\ContainerInterface;

class DisclaimerPageMiddlewareFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $viewRenderer = $container->get('ViewRenderer');
        $viewManager  = $container->get('ViewManager');

        return new DisclaimerPageMiddleware($viewRenderer, $viewManager);
    }
}

What’s happening here is that the DisclaimerPageMiddlewareFactory’s __invoke method will be provided with the application’s DI container. By having access to the DI container, the ViewRenderer and ViewManager services can be retrieved and passed to the DisclaimerPageMiddleware’s constructor.

Note: I’m not going to get in to a debate on the merits of taking this approach or not. I’ll leave that for another day.

Step 3 - Configure the ServiceManager

The middleware class for rendering the page content, along with a factory class for instantiating it has now been created. Now we need to register it as a service with the DI container, so that we can use it in the application. To do that requires an addition to your module’s service manager configuration, such as in the example below.

Here, in module\Application\config\module.config.php, we’ve added a service, who’s name is the name of the class, and will be provided by the DisclaimerPageMiddlewareFactory class which we saw in step two.

<?php

return [
  'service_manager' => [
    'factories' => [
      DisclaimerPageMiddleware::class => DisclaimerPageMiddlewareFactory::class,
    ],
  ],
];
Note: I use class name resolution extensively. Here’s more information on it, if you’re not familiar with it.

Step 4 - Configure the Routes

With the service now available, the final step is to refactor (or create) the route to use the new page action middleware. What we’re doing here is setting up the default route / which is a Literal route; that is, there are no query parameters, sections or other kinds of information able to be set in, or pulled from the route.

The key point to note is the middleware key in the defaults array. This is where you define the middleware (or stack of middleware) which will be used to handle requests to this route.

// in module\Application\config\module.config.php
return [
    'router' => [
        'routes' => [
            'home' => [
                'type' => Literal::class,
                'options' => [
                    'route'    => '/',
                    'defaults' => [
                        'middleware' => DisclaimerPageMiddleware::class
                    ]
                ],
            ],
        ]
    ]
];

As this tutorial is focused on providing an introduction to migrating Zend Framework 2 applications to Zend Expressive, I’m not going in to detail about middleware, or how you can stack middleware together for more sophisticated setups.

If you’d like to know more however, then this blog post by Zend Framework project lead Matthew Weier O’Phinney, provides an excellent overview on the topic.

In Conclusion (tl;dr)

And that’s how to begin migrating your existing Zend Framework 2 applications to Zend Expressive. This approach provides access to the power and flexibility which Expressive provides, via PSR7 and Middleware, without having to rebuild your application(s) from scratch.

If you need consulting support migrating your existing Zend Framework 2 application(s) to Zend Expressive, please get in touch.


You might also be interested in these tutorials too...

Mon, Aug 22, 2016

How To Use Laravel’s Eloquent ORM with Zend Expressive

Laravel’s Eloquent ORM isn’t likely the first one you think of when using Zend Expressive. You likely think of Zend\Db or Doctrine. But, with a little bit of work, it’s possible to use Eloquent with Expressive. Today’s tutorial shows you how - step-by-step.

Tue, Aug 9, 2016

The 3-Step Guide to Downloading Files in Zend Expressive

A common requirement of web-based applications is to upload and download files. But, out of the box, there’s no simple way to download them in Zend Expressive. This tutorial shows you how - step-by-step.

Tue, Jul 5, 2016

What I Learned Building a Zend Expressive Application

Zend Expressive is an excellent framework for building modern applications; whether micro or enterprise-sized applications. But that doesn’t mean that it’s the easiest to get up to speed with. Today I’m going to share with you what I’ve learned, building applications using it.


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus