Preparing your Zend Framework 3 Controllers. Bye ServiceLocator.

The recent march toward ZF3 has signed the blockade that keeps the service locator out of all controllers. If you've been developing a ZF2 app, you're probably fixing your composer to not install zend-mvc 2.7+. Pause that version freeze, patch below.

The deprecation of this pivotal auto-service is ratified by an academic mix of "it's an anti-pattern", code rigor and testability - all true. However rationalized, the real world impact can be a PITA. If you want to stay up-to-date, you've got to face the music. I did anyways, in looking at the bevy of controllers I had to deal with if I wanted to keep current.

Anecdotal, I hit IRC quickly to ask "how are you guys dealing with this?". All I got was "not upgrading yet".

If you've read this far, you're in my shoes -- keep reading!

Here then, is an abstract factory that you can modify to help you get around this zend-mvc change. All you have to do, is write constructors with the right class names - and this abstract factory will use reflection to inject your dependencies for you. What's more, some cheat code can sub parts in, for example: if you use "array $config" or other aliases as constructor parameters, it'll get the ZF config and so forth.

The abstract factory relies on the fact that you are using ::class to declare your service manager components. If you're not using ::class, you should! e.g.:

Controller | fix dependencies

Your controller constructor is where the factory discovers dependencies using reflection. Note, in cases where you have uber complex setup, you should probably stick to a bona-fide factory. That's ok, ZF will match factories before it does abstract factories. The lazy factory can be your backup.

After this, it's just a matter of removing any reference to $this->getServiceLocator() in your controller code. Remove the locator, add the dependency you were locating to the constructor; rinse and repeat.

Good luck with your migration! I always welcome improvements and feedback!

I kept this in post-migration. It lets me prototype just as fast as when I had the SL readily available and makes things a bit less nebulous when comparing tests to controllers/services, etc.