Save Time Instantiating Mezzio Handlers With the Reflection-based Abstract Factory

Save Time Instantiating Mezzio Handlers With the Reflection-based Abstract Factory

If you’re creating handlers in a Mezzio application and don’t want to spend time building and maintaining custom factories to instantiate them (or other classes), you need to know about the Reflection Factory.



Recently, as you may know, I’ve been building a small user authentication module for an upcoming tutorial for a European magazine. As part of developing the application, I followed my standard approach of using Mezzio’s Command Line Tooling to quickly bootstrap handlers and middleware, such as by running the following command.

composer mezzio mezzio:handler:create "App\Handler\ForgotPasswordHandler"

If you’re not familiar with Mezzio’s command line tooling, the above command generates a PSR-15 Handler class and a factory to instantiate it, registers the handler with the application’s DI Container, and creates a view template for it.

Using the command greatly simplifies Handler creation, as it avoids a large number of potential mistakes and bugs that may creep in when creating them manually. Moreover, you know that the files will be created in a consistent manner. However, while the command brings a lot of efficiency to Handler creation, depending on your use case, it may create more work than necessary.

This might seem like a strange thing to say, given my support for the command, but hear me out. Perhaps you’re creating a Handler, and it’s rapidly evolving as the needs themselves evolve. For example, you might be building a Handler that performs user authentication, retrieves content from a social media service such as LinkedIn or Twitter, or provides some other service that requires an ever-growing number of constructor parameters.

In this case, as you iteratively refactor the Handler class you also have to iterate on the Handler’s factory. Otherwise, an exception will be thrown when attempting to retrieve the service from the DI container or when attempting to use it. Yes, it’d be great to have requirements mapped out clearly and concretely ahead of time. But that’s not always practical nor possible.

So, what about iteratively refactoring the handler as the needs of the project evolve without needing to keep refactoring the handler’s factory class? Better yet, why not skip creating a custom factory altogether?

At first blush, this might seem like a ludicrous thing to say, no? After all, if there’s no factory for the handler, how can it be instantiated? Fair point.

However, if you revisit what I said, I only said skip creating a custom factory. You still need a factory to retrieve the constructor parameters so that the class can be instantiated. But that doesn’t mean that you have to create said factory yourself.

If your Mezzio application is using laminas-servicemanager as it’s DI Container, you’re in luck. Enter the Reflection-based Abstract Factory (or Reflection Factory). This class uses PHP’s Reflection API to introspect which constructor parameters are required and, where possible, retrieve them from the DI Container (if they’ve been registered).

Worried about performance?

Given that the class uses reflection, you may have concerns about application performance, as the Reflection API does have a performance overhead. It’s a fair concern for a production application, but during development, I’d suggest not.

Remember, the recommendation to use the Reflection-based Abstract Factory is only during initial development. That way your energies can stay on the Handler’s logic not instantiating it.

Then, after the Handler’s state becomes stable enough, you can use a more performant factory, such as a custom one or perhaps the Config Abstract Factory.

Some things to bear in mind about the Reflection Factory

That said, there are a few things to bear in mind when using it:

  • If a class' constructor has a parameter named $config type-hinted as an array, it will receive the application’s "config" service (i.e., the merged configuration).

  • An empty array will be injected for parameters type-hinted as an array but not named $config.

  • Scalar parameters will result in the factory raising an exception, unless a default value is present. If it is, however, that value will be used.

  • If a service cannot be found for a given typehint, the factory will raise an exception detailing this.

How do you use it?

To use the Reflection-based Abstract Factory instead of a custom factory you just need to use it to instantiate the handler when registering the handler with the DI container. In the relevant module’s ConfigProvider.php file, in the array returned from the getDependencies() method, add your Handler class to the factories element setting the ReflectionBasedAbstractFactory to instantiate it.

'factories'  => [
    Handler\ForgotPasswordHandler::class => ReflectionBasedAbstractFactory::class,
],

That’s how to save time instantiating Mezzio Handlers by using the Reflection-based Abstract Factory

If you’re rapidly prototyping application, I highly recommend using the Reflection-based Abstract Factory so that you can concentrate on the Handler’s logic and not worry about instantiation, until the code’s semi-stable.

I’d love to know what you think in the comments.

Want to Learn More About Mezzio?

Mezzio Essentials teaches you the fundamentals of PHP's Mezzio framework — the fundamentals that you need — to begin building get paid for applications with the Mezzio framework right away. It’s a practical, hands-on approach, which shows you just enough of about the underlying principles and concepts before stepping you through the process of creating an application.

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

How to Use a CSRF Token in a Mezzio Application
Tue, Mar 2, 2021

How to Use a CSRF Token in a Mezzio Application

No matter how small your web app may be, security is essential! In this tutorial, you’ll learn how to add a CSRF token in forms used in Mezzio-based applications, to prevent attackers from being able to force your users to execute malicious actions.

How to Manually Create a Mezzio Application
Thu, Aug 13, 2020

How to Manually Create a Mezzio Application

If you want to build applications in PHP — from one-page apps to enterprise-grade applications — PHP’s Mezzio framework is a excellent framework to choose. In this tutorial, which is an excerpt from my new book, Mezzio Essentials, I’ll show you how to manually build an application in Mezzio.

Goodbye Master Zend Framework. So Long. Farewell.
Wed, Jul 8, 2020

Goodbye Master Zend Framework. So Long. Farewell.

It’s with some sadness, that earlier this week, I wished a fond farewell to the biggest blog I ever created, Master Zend Framework. Given that, it only feels right — and responsible — to talk about what motivated the decision to close the blog, and what the future holds for the blog’s content.


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