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.
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.
Want to Learn Zend Expressive — Quickly?
Get the book that teaches the fundamentals that let you begin building applications — right away.
It's a practical, hands-on approach, which shows you just enough of how Expressive is put together and how to use it, while not getting lost in things that aren't necessary
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.
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.
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.
Join the discussion
comments powered by Disqus