Zend Expressive is a great foundation on which to build an application, especially if you want to keep it small and lean. But out of the box, form view helpers aren’t available. Here’s how to make them available.
Zend Expressive is a great foundation on which to build an application, especially if you want to keep it small and lean. But out of the box, form view helpers aren’t available. Here’s how to make them available.
Recently, as I’ve been continuing my journey learning all about Zend Expressive, primarily by building a client application with it, I’ve consistently learned just how much of an improvement it is over the previous approach of the Zend Skeleton project.
For what it’s worth, I’m not wanting to detract from the Zend Skeleton project. It’s an excellent one, one well worth using as a foundation for a wide variety of projects.
However Zend Expressive, at least to me, is the next step in the continuing evolution of Zend Framework. It’s a lot lighter, a lot less involved, and all round, a lot simpler to work with.
But, given that it’s a microframework approach, there’s a lot of features which it doesn’t implement out of the box; features which you might expect to be automatically available, depending on your previous development experience.
So it was with me, when it came time to build and render the login form for the application. I assumed that I’d be able to use the Zend\View
form helpers which I’d come to rely on for so long, in my templates.
Well, no I couldn’t.
I was a bit lost at first as to why they’d not be available. But I reminded myself that I was now working with a microframework, not a full-stack framework. And when that’s your starting point, why would you have form view helpers available by default?
They’re not essential to building an application. They’re an optional, nice-to-have, feature, one which you’d bring in later. They’re one which, whilst they make life easier when they’re present, aren’t strictly necessary.
For me however, they really make building the kinds of applications I develop easier. So I wanted to make the available. The question was, how?
What To Do?
As always, I asked both on the Zend Framework 2 Facebook group, and in #zftalk on IRC. Abdul Malik Ikhsan was kind enough to answer my enquiry by saying:
If you need another view helpers except url and serverurl, may need to create custom ZendViewRendererFactory and point expressive renderer to your own factory
What is ZendViewRendererFactory?
So I started exploring the class and found that that was the right class to start with. It sets up the Zend\View service, when Zend\View is used as the view layer with Zend Expressive.
It has a private method, injectHelpers
, which injects two helpers, url
and serverurl
into the list of available helpers. However, given that the method has private visibility, I couldn’t override the method in a sub-class.
Doing so would always result in the parent method being called. So I created a new class called App\ServiceManager\Factories\ViewRendererFactory.php
. If you’re wondering why that namespace, it’s a clear, logical, and consistent naming convention.
Now that I had my class which would handle injecting the form view helpers, in addition to the existing two, the question was, how would I actually inject them? If you have a look in ZendViewRendererFactory
, in the injectHelpers
method, you’ll see the following line:
$helpers->setInvokableClass('serverurl', ServerUrlHelper::class);
What it does is to add a view helper to the helpers list, specifying the name it will be referred to by the first parameter, and the invokable class which provides the functionality as the second.
Ok, not so hard. I just have to now do that for all the form view helpers. To do that though, we first have to make them available. Gladly, they’re nicely packaged up in the zend-form package.
If you don’t have them available in your package, use Composer to add them by calling composer require zendframework/zend-form
from the project root. Then, under vendor/zendframework/zend-form/src/View/Helper
you’ll see that there’s thirty nine of them.
You might be thinking, at this point, that we’re going to have to add thirty nine calls to setInvokableClass
to add them all. What a lot of work that’d be?
A Simple Way to Inject the ViewHelpers
Well no, we don’t have to. Why? Because under vendor/zendframework/zend-form/src/View/
is a file called HelperConfig.php
. Originally designed to be used with the ZF2 ServiceManager, it has a protected associative array, called $invokables
, which contains the name and class information which we need.
However we can’t use it directly, as there’s no method available to retrieve $invokables
. But not to worry, to retrieve the array, we next create a new class, called App\Form\View\HelperConfig.php
which extends HelperConfig.php, as below.
<?php
namespace App\Form\View;
use Zend\Form\View\HelperConfig as BaseHelperConfig;
class HelperConfig extends BaseHelperConfig
{
public function retrieveInvokables()
{
return $this->invokables;
}
}
In the class, you can see that I’ve added a new, public, method, which returns $invokables
. Using that, we can now retrieve our list of invokables, and inject them in to the available list of helpers.
To do that, though it feels like a clear case of code duplication, I first copied the __invoke
and injectHelpers
methods to my new ViewRendererFactory
class. Then, after the previous call to setInvokableClass
, I added the following code.
$helperConfig = \App\Form\View\HelperConfig();
foreach ($helperConfig->retrieveInvokables() as $key => $value)
{
$helpers->setInvokableClass($key, $value);
}
This will retrieve and iterate over the list of invokables adding them to the available list. With that done, I’ve added all the form view helpers to the list of available helpers; a list which can be changed later, if needed.
Updating the ServiceLocator Configuration
Now, there’s only one more thing to do; we need to update the service locator dependency configuration to use the new renderer factory, instead of the default. To do that, in config/autoload/templates.global.php
, update it so that it looks as follows.
'dependencies' => [
'factories' => [
'Zend\Expressive\FinalHandler' =>
Zend\Expressive\Container\TemplatedErrorHandlerFactory::class,
Zend\Expressive\Template\TemplateRendererInterface::class =>
App\ServiceManager\Factories\TelcoSwitchViewRendererFactory::class,
],
],
What this will do is tell it to use our new class for instantiating the view renderer, instead of the default.
Don’t Forget Composer
One last thing, if you’re following along, make sure that you run composer dumpautoload --optimize
so that your new classes are made available via Composer’s autoloader. Otherwise you’ll encounter an exception when you run the code.
With all these changes made, we can now use Form ViewHelpers in our .phtml
templates as we could with Zend Framework 2, using the ZF2 Skeleton App project.
## Over to You
Are you rendering forms in your Zend Expressive applications? How have you implemented them? What’s your experience with it? Share your thoughts in the comments and let’s have a hearty conversation about it.
Join the discussion
comments powered by Disqus