For the longest time, Zend Framework hasn’t had the strongest support for command-line tooling and scaffolding. However, in recent times, that’s all changed. Come find out how to use Expressive’s new tooling support to create modules and middleware rapidly.
For the longest time, Zend Framework hasn’t had the most robust command-line tooling and scaffolding support.
In stark contrast, other frameworks — especially Laravel, and its excellent Artisan command — have had far stronger tooling support and as a result, have been far easier for building projects.
However, that’s all changed!
Since the release of Zend Expressive Skeleton 2.0.2, Zend Expressive’s command-line tooling support has been rapidly developing.
It’s provided through a package called, aptly, Zend Expressive Tooling.
In a nutshell, it supports three things:
- Middleware creation
- Module creation
- Migration from version 1 to version 2 of Zend Expressive
Today, I’m going to talk through points one and two, and cover point three in a separate post (likely next week).
Short on time?
If you don’t have a lot of time spare to read through the post, get the essentials in episode 26 of the podcast.
Installation
Like any, modern, PHP package Zend Expressive Tooling can be installed using Composer — would you have expected anything less?
To do so, run the following command:
composer require --dev "zendframework/zend-expressive-tooling:^0.4.4"
Alternatively, ensure that your project’s composer.json file at least looks like the following, and run composer update
afterwards:
"require-dev": {
"zendframework/zend-expressive-tooling": "^0.4.4"
},
With the package installed, you can run it, from the terminal, by calling ./vendor/bin/expressive
.
If you do so, you’ll see the following as part of the output:
middleware
middleware:create Create an http-interop middleware class file.
migrate
migrate:error-middleware-scanner Scan for legacy error middleware or error middleware invocation.
migrate:original-messages Migrate getOriginal*() calls to request attributes.
migrate:pipeline Generate a programmatic pipeline and routes from configuration.
module
module:create Create and register a middleware module with the application
module:deregister Deregister a middleware module from the application
module:register Register a middleware module with the application
I’ve only included this section of the output, as the rest is the standard output for a command-line tool built using Symfony’s Console Commands package; the output which you’re likely already used to seeing.
As I mentioned earlier, the tool has three areas of support; one for middleware, one for migration, and one for modules.
Let’s start with middleware.
Middleware Creation
As you can see in the command output above, you can create an http-interop
compliant middleware class.
This class utilizes the new approach to middleware in Zend Expressive 2.0, one based on the upcoming PSR-15 standard.
Let’s assume that I have a greenfield Zend Expressive project and want to create my first piece of middleware for it, called Footer
, inside the existing App
namespace.
To do so, we would run the following command:
./vendor/bin/expressive middleware:create "App\Middleware\Footer"
This one command creates the directory Middleware
under src/App/
, if it doesn’t already exist, and in there create a new middleware class, called Footer.php
, with the following contents:
<?php
namespace App\Middleware;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
class Footer implements MiddlewareInterface
{
/**
* {@inheritDoc}
*/
public function process(
ServerRequestInterface $request,
DelegateInterface $delegate
) {
// $response = $delegate->process($request);
}
}
Here, you can see a basic template for a new middleware class ready to be fleshed out.
There’s no need to create either it or the directory structure, by hand anymore.
However, two things are worth noting:
- The tool doesn’t update Composer’s autoloader; so you’ll have to do that manually, by running
composer dump-autoload
.
- If the namespace you’ve provided doesn’t exist you’ll see the following error:
[Zend\Expressive\Tooling\CreateMiddleware\CreateMiddlewareException]
Unable to match Api\Middles\Footer to an autoloadable PSR-4 namespace
So make sure that you’re using an existing namespace before you run the command.
Want to Learn Expressive’s Essentials?
If you want to get a jump-start on building applications using Zend Expressive, then don’t miss my upcoming book and course! In it, you’ll learn all about Expressive’s core concepts and components, as well as how to create an application manually and by using the skeleton installer. Share your email address to find out when it’s ready.
Module Creation
Now let’s see how to manage modules.
Specifically, let’s see how to create, register, and deregister a module.
What is a Module?
If this is your first time hearing about modules in Zend Expressive, and you’re already familiar with Zend Framework 2, they’re not technically the same thing.
Whereas Zend Framework 2 supported modules by using the Module Manager, Zend Expressive’s modules are based only on configuration and directory structure.
Have a look at the following directory structure from an initial expressive application which I’ve created for this tutorial.
src
├── App
├── Action
│ ├── HomePageAction.php
│ ├── HomePageFactory.php
│ └── PingAction.php
├── ConfigProvider.php
└── Middleware
└── Footer.php
You can see, under src
, that there is one directory: App
; which you will be familiar with if you use the Skeleton Installer to create your Expressive projects.
It has three action classes and a ConfigProvider class “How To Simplify Zend Expressive Configuration with ConfigProviders” — it also now has the Footer middleware which we created earlier.
That directory, thanks to the ConfigProvider class, is a module in Zend Expressive terms.
The code inside that directory isn’t (or shouldn’t be) specific to this application, and could be packaged up into an independent Composer package to be used in any Expressive application.
I hope that this clarifies what a module is.
Create a Module
With that explanation out of the way, let’s see how to build a module called Generic
.
As the name implies, it won’t do much.
From the command-line, run the following command:
./vendor/bin/expressive module:create Generic
After the command completes, if you look at the directory structure of src
, you’ll now see that it looks like the following:
src
├── App
│ ├── Action
│ │ ├── HomePageAction.php
│ │ ├── HomePageFactory.php
│ │ └── PingAction.php
│ ├── ConfigProvider.php
└── Middleware
└── Footer.php
└── Generic
├── src
│ └── ConfigProvider.php
└── templates
We have a new directory (module) called Generic
, which has a ConfigProvider class and a templates directory.
This might not seem too surprising, but have a look at composer.json where you’ll see that the PSR-4 autoload configuration’s been updated to look like the following:
"autoload": {
"psr-4": {
"App\\": "src/App/",
"Generic\\": "src/Generic/src/"
}
},
What’s more, if you look in config/config.php
, you’ll see that the module’s ConfigProvider has been included so that it is active in your application.
Here’s a (trimmed) snippet:
<?php
use Zend\ConfigAggregator\ArrayProvider;
use Zend\ConfigAggregator\ConfigAggregator;
use Zend\ConfigAggregator\PhpFileProvider;
// To enable or disable caching, set the `ConfigAggregator::ENABLE_CACHE` boolean in
// `config/autoload/local.php`.
$cacheConfig = [
'config_cache_path' => 'data/config-cache.php',
];
$aggregator = new ConfigAggregator([
\Generic\ConfigProvider::class,
// ...trimmed for readability
], $cacheConfig['config_cache_path']);
return $aggregator->getMergedConfig();
If you run your application at this point, you won’t see a lot.
However, you can quickly get started creating middleware, templates, and so on to flesh it out, without having to look after the boilerplate work.
Register an Existing Module
Now, let’s say that you already have a module which you were working on by hand before you integrated Expressive Tooling into your project and want to enable it.
Assuming that your module was called Authentication
, to do so you would run the following command:
./vendor/bin/expressive module:register Authentication
This command updates composer.json
and config/config.php
, making your module active.
De-register an Existing Module
If you want to disable an existing module, say because there’s a bug you are having trouble fixing, you’re planning to deprecate the module, do testing when it’s not present, and so on, here’s how to do it.
Assuming that your module was, again, called Authentication
, to disable it, you would run the following command:
./vendor/bin/expressive module:deregister Authentication
This command:
- Updates
composer.json
, removing the module from the PSR-4 autoload configuration
- Updates
config/config.php
, removing the module from the ConfigAggregator
array.
These actions deregister your module, making it inactive.
It’s worth noting that the command does not remove any source files!
So, don’t get worried if you think it’s going to do anything like that.
In Conclusion
And that’s how to use Zend Expressive’s new tooling support to create middleware, as well as to create, register, and deregister modules.
I hope that you found it helpful and that you can see that Expressive is growing by leaps and bounds.
I hope that you also see that Expressive is catching up to other frameworks, such as Laravel, who have had extensive tooling support for some time.
Have a go and experiment with it.
I hope that it helps you spend less time on the setup aspects of your apps, and more on the development.
Next week, we’ll see how to use the tool to migrate an Expressive application from version 1 to version 2.
Many thanks to Rob Allen (@akrabat) for being the technical reviewer on this tutorial.
Join the discussion
comments powered by Disqus