Zend ServiceManager - Web Application Development Simplified
The Zend ServiceManager simplifies the web application development process by making configuration a breeze. In this, the 4th post introducing Zend Framework 2, you will learn what the ServiceManager is how to use it and how it simplifies applicaiton development time.
The Zend ServiceManager simplifies web application development in a number of ways, primarily by making configuration a breeze. In this, the 4th post introducing Zend Framework 2, you will learn what the ServiceManager is, how to use it and how it simplifies app development time.
Welcome to the Zend Framework 2 Introduction 4-part series finale. Recapping the series so far:
- In part one, we went through Dependency Injection (DI)
- In part two, we looked at Modules and the ModuleManager
- In part three, we looked at the EventManager
In this, the fourth and final installment, we look at the ServiceManager component. This is a highly critical, but potentially misunderstood, aspect of the framework. One that, when understood, makes the rest of the framework a breeze (well, close).
From reading various blog posts and comments, it’s often believed that the ServiceManager over-complicates the entire framework. Some people say it’s an attempt to: out Java Java.
I - completely - disagree!
I believe that it’s this fundamental concept that makes the framework simpler, that makes developing web applications with it easier, less stressful and more maintainable. I hear scoffing, I hear peals of laughter, I hear the embers of a flame war being stoked to burn me alive at the stake.
To support my point, in this post, I’m going to do 3 things:
- Give you a good introduction to what the ServiceManager is
- Show you how to configure it
- Step you through a hands-on example of using it
Stay on to the end as we consider the critical question.
What is the ZF2 ServiceManager
Put in simplest terms, the ZF ServiceManager component is an implementation of the Service Locator pattern; in short a simple application registry that provides objects (in a lazy loaded fashion) within application as needed - but with some nice additions.
It allows us to perform Inversion of Control (IoC), which allows us to remove dependencies and tight coupling from our applications. The result of this, when combined with dependency injection and simple event management is applications that are simpler to build, test and maintain.
You can try to think of it in more complex ways if you’d like to, but really there’s no need. Where it does get a little complicated however, at least initially, is how it’s all configured. I grant you, that does take a bit of getting your head around - but not too much.
How Do You Configure It?
The Service Manager is able to be configured in 7 key ways. These are:
- abstract factories: This is one of a fully qualified class name, or an object implementing Zend\ServiceManager\AbstractFactoryInterface. This approach provides flexibility and extensibility to the ServiceManager. If, on request, the ServiceManager isn’t able to locate a class, it iterates through the registered Abstract Factories to see if any of them are able to satisfy the object request.
- factories: A fully qualified class name, PHP callable object, or a class implementing Zend\ServiceManager\FactoryInterface. These handle the dependency injection aspect of the ServiceManager.
- invokables: A string, which is a fully qualified class name, able to be instantiated later.
- initializers: A fully qualified class name, PHP callable object, or a class implementing Zend\ServiceManager\InitializerInterface. If listed, will be applied to objects retrieved from the Service Manager to perform additional initialization.
- configuration classes: This is a class implementing Zend\ServiceManager\ConfigInterface. Classes implementing this interface are able to configure the Service Manager, performing the initialization that is covered in these seven points.
- aliases: An associative array of aliases to services (or aliases to aliases). It may not seem like a good idea, but from a readability perspective, I believe this is an excellent technique to have available.
- shared: Depending on your application or circumstance, you may want to provide single access to an object, or return a new copy on each request. By default, when an object is retrieved from the Service Manager if it’s the first request, the object is instantiated and returned. If it’s any after that, the original object is returned.
What’s really great about this approach, is that each module loaded or created can also be a service provider. To do so, they need to do one of the following:
- Implement the Zend\ModuleManager\Feature\ServiceProviderInterface
- Implement getServiceConfig()
As the manual indicates, this function needs to return:
- An array or Traversable object
- The name of a class implementing Zend\ServiceManager\ConfigInterface
- An instance of either Zend\ServiceManager\Config, or an object implementing Zend\ServiceManager\ConfigInterface.
A Simple Code Example
I’ve been creating a Generic module throughout this series and in it, I’ve added a simple model that lets me retrieve information from a SQLite database. So what better choice to use for an example that that.
In module/Generic/Module.php, I have an implementation of getServiceConfig which is as follows (formatted for readability):
You can see here I’m configuring it with the &'factories&’ option. In there I have two options:
Both of these use anonymous functions for the configuration. Now, let’s pop over to where they’re used in the IndexController. The default action, Index, goes as follows:
It calls the getAlbumTable method, which is as follows:
Now that we have the configuration and usage together, let’s see how it works.
In indexAction, we set a variable &'albums&’, which is the result of calling the
fetchAll method on the object returned from the
getAlbumTable method, we retrieve a copy of the application Service Locator object via the getServiceLocator method. We then retrieve the
AlbumTableGateway object, by passing the name, as a string, to the get method of the Service Locator object.
Assuming the object is in the Service Locator registry and suitably configured, it’s then passed as the return value from the function, allowing us to call the method on it.
Looking back in to the configuration of the object we see it as follows:
We see we have a factory configuration, labelled AlbumTableGateway configured by an anonymous function.
You can see we first we use the ServiceManager to get access to the application-wide database adapter (I’ll cover it in a sec), by retrieving the object configured with the string Zend\Db\Adapter\Adapter.
We then create a new ResultSet object and set the prototype to be an Album object. When that’s done, we then create and return a new TableGateway object, specifying the type, database adapter and result set prototype.
Now, I’m deliberately skipping over delving in to the intricacies of the Zend_Db class here - as it’s really, a bit outside the purposes of this post. But I encourage you to give it a good read in addition to what you read here.
Now, for the final part, in config/autoload/global.php I have the following configuration:
You can see how the Database adapter is made available, configured using the same convention - allowing me to query a SQLite version 3 database throughout the application.
Don’t forget, all code is available for download from the Malt Blue Github repository. Grab a copy of it and tell me what you think.
What We Have Learned?
This process of stepping through the configuration and usage of the ServiceManager has shown us X things:
- Configuration Is Simple: Whilst a bit involved (because of all the locations where configurations can be located) it actually is simple because it follows a clearly defined set of conventions and stored in a standard set of locations.
- It’s Easy to Debug: By having standard conventions and locations, we can track configurations in the application logically and systematically.
- It Works with Across Modules: Whereas in Zend Framework 1, we had to jump through hoops to work with multiple modules, in ZF2 it’s all baked in. Just follow the conventions and it works.
- Applications Are More Dependable: This is a bit of a reiteration of the previous points. But by being able to configure applications reliably, simpler, in a readily debuggable manner, you spend less time and effort, effort which can be spent more meaningfully in other aspects of development (and your business).
- Easier to Maintain: When applications as more consistent, predictable, debuggable, logically (in my mind if nowhere else), they’re easier to optimise. Why? Because you’re working with a known quantity. Possibly a little “boring” but following convention makes adding new components quicker and more predictable. Being a maintainer, you know how applications hang together, you know where to look, the options which can be used, how to override them and so on.
Does it Really Make Development Simpler?
This is the burning question in this post. Does it really make web application development simpler? In short, yes. Now, at first, there’s a lot to cover, there’s a lot to learn. I grant you that.
There’s the 7 points mentioned above and you have to work with the different ways in which each work. Fine - I agree it does require work.
But think about any skill you’ve learned. Whether it was riding a bike, learning calligraphy, building running fitness, or what I’m doing - learning German.
At first it requires effort, it requires discipline and it requires concentration. It’s not easy, sure. But with time, this new skill makes doing what you used to do much simpler, such that you do more in less time, with less effort, with less concentration.
Consider the amount of work that went in to Zend Framework 1 applications and configuring them - especially integrating modules and the associated configurations.
As Evan Coury well said - they sucked!
There was the application.ini file, the module configuration that you could choose from a number of good implementations to get it to work, you could roll your own option and more.
Now, we have the option to spend some time learning, but with the result of ultimately writing cleaner applications, which are simpler to maintain both in terms of time and effort.
We’ll have applications which are much more:
I believe, therefore, it’s worth the investment of your time to learn. I believe it really is a blessing (potentially in disguise). I’m a learner, like you. So I want to know what you think, if you disagree with me. If you do, comment and tell me.
Get the Code
The code for this post - and all the posts in the Zend Framework 2 introductory series - is available on the Malt Blue GitHub account. I encourage you to clone a copy, play with it, comment on it, improve on it.
Over to You
Do you agree with me or want to flame me right now? If you agree with me that the ServiceManager will simplify use of Zend Framework 2, share with us how in the comments.
Alternatively, if you agree more with others, that it’s a pointless, over-complication, of what should be kept simple, say that too.
We can all grow through shared, constructive, opinions.
You might also be interested in...
- Zend Framework 2 Modules - The Application's Heart
- \Zend\Db\Sql - Build SQL Where Clauses Easily and Efficiently
- Use RouteMatch in Zend Framework 2 For Easy Routing
- How to Use the Zend Form ViewScript Decorator In All Modules
- Zend Form Mastery with Zend Config - Part 1 Custom Filter Paths
comments powered by Disqus