CallableResolver.php

Controller in Slim Framework 3

Slim Framework 3 is undeniably a great tool to build a fast web service. The simplicity it offers allows us to architect our own project structure and choose the libraries as much as we want. The framework is heavily propped by the famous Service Container called Pimple, and it accomodates most of the app components like View, Router, HTTP Request and Response, making them to stay modular and atomic.

However, many developers are still trying to adjust the framework to work with MVC pattern, particularly the Controller part. Lot of ways to do this, for example: this, this, and this. Well, they might just work perfectly well but there are some things that I feel don’t satisfy me personally. Let me put it into words.

#1 Example

The inconvenience I feel in the first example, is we have to register all of our controllers in the container and pass the dependencies manually and remember the order like:

$c[\App\Controller\Page::class] = function($c) {
return new \App\Controller\Page($c->view, $c->router);
}

when all what I want is just, call the controller in the router, and boom, it works.

#2 Example

In order for the controller to know its dependencies, we have to inject the whole container object to the controller via the setter method. While I think this is the easiest way to accomplish the task, but errrmm according to my friend this is considered a bad practice since the controller now acts as a God Object that knows everything, and there’s no way for the controller to know which dependencies it’s using. You can also support the argument by reading the comment section of the article.

#3 Example

This one, I believe, is a little bit more like the second example, except it injects the whole app object to the controller instead of the container. Again, you know the reason already.

What I propose

Here’s what I want: I just want a simple controller/action class, set with all its dependencies in the constructor, and the app magically resolves them without me injecting manually and remembering the order. It’s a bit like Laravel Container, but yeah you got the point.

So, referencing to the crystal-clear explanation by Christopher Geary, I adjusted his code to work with Slim Container:

The code I’m using embraces the magic PHP \ReflectionClass provides. In general, it’s a bit like Factory in creating concrete class in PHP. For instance, if we do

$class = new \ReflectionClass(‘\App\SomeClass’);

then $class variable will know anything about SomeClass class, including the methods it has, the properties, traits it’s using, comment block of the class and individual method, constructor, even the constructor variable, default value, and its type! This is a good way to go if you intend to orchestrate your class before actually using it later. You can read more about it here.

The embedded gist code above will search for the dependencies at the constructor and tries to resolve it by matching the variable name against the container key first. If it fails, it will evaluate whether the dependency is instantiable. And if not, it will just return the default value or otherwise throw an error. If it is (instantiable), create the class and find out again if the dependency class has also its own dependencies. This goes on and on recursively untill the class is satisfied with all its dammed dependencies.

I haven’t tested it yet (poor me I’m not good at PHPUnit or similar stuff), but so far it just works for me. This way, I can go with as many dependencies as I want at the constructor without worrying the order, and of course without registering all of my fucking classes in the container. If you have interesting points about this article, please don’t hesitate to comment out below.

And as always, happy coding!