Silex comes packed with its very own built-in dependency injection container called Pimple (this is also a standalone dependency injection container available here) which is a very lightweight, yet powerful, container. How does it work?
You may not have come across the term dependency injection yet, or you may have heard about it but don't understand what it is. Don't be afraid — it sounds more complicated than it really is.
Let's suppose we have an application that runs a blog. It's very easy to just pass the entire application object into every class you instantiate, so that all of the components of the framework are available to you whenever you need them. The problem is that every part of your application is bound to every other part. If you ever need to use just one little part of that application somewhere else, you're going to have to go through the code line by line and make sure that everything you needed will now be available when needed. It will probably be easier to just rewrite everything.
But Imagine that what you did was to pass every object's dependencies to the object when you instantiated that object. The class would always have what it needed to operate, and you could move it around or do with it as you please — the only thing you need to do is make sure the dependencies of that object are passed to it when you create the class.
This is dependency injection — injecting the class dependencies into a class (usually when instantiated), thereby decoupling the application from your application. What you get at the end of the day is a reusable piece of code that is simple to modify and maintain. It's also extensible.
Let's look at the code, remembering from last time that when you instantiate a Silex application you are in fact building your dependency injection container.
In the diagram below the $app variable is the dependency injection container.
The application object is, in fact, an array (yes, I know…) and so to store data in it all you have to do is something like the follow:
And to access Peter's surname we access it in the normal way you would access anything in an array.
But the real power of Pimple is when you create objects.
Let's say we want to instantiate a custom controller when a certain URL (route) is hit on the server. We would do that like this:
Let's look at what this code is doing.
Line 9: This is our first line of new code. We're assigning the validation object to the
$app['validator.class'] variable, making it easy for us to use in the future.
Line 13: This is doing the same for the mailer class.
Line 17: We're injecting the validation and mailer classes into the user class. Note we no longer need to call the class directly, it's now an object stored in the dependency injection container.
Note line 37 — here we are receiving the injected dependencies, and we can use PHP type hinting to make sure we're getting the exact class we need. Once these objects have been assigned to the class properties (on lines 39 - 40 ) they can be used as required.
The really nice thing about how Pimple handles dependency injection is that classes are only instantiated when you use them, and not a moment before. Lazy loading is very good for resource management.
This concludes our look at Silex's use of dependency management. As always, I hope you have learned something new.