Although I really enjoy the concept of bindings implemented in ICanBoogie, I recognize it can be challenging when your application has thousands of dependencies. Also, as I'm implementing a message bus for ICanBoogie, I recognize the value of a dependency injection container to instantiate all the lovely message handlers, and because I really like Symfony's Dependency Injection component, I decided to use it for this first implementation, trying to create something as transparent and flexible as possible.
ICanBoogie favors functional programming to interfaces in many places, and uses callables for a lot of things such as controllers, event hooks, prototype methods, operations, proxy… Thus, I had the idea to create service references as callables, as they would be used without requiring any code change. They are very simple things really, they obtain the service they reference through a service provider, pass the arguments, and return the result.
The following example demonstrates how to reference a service, and invoke it with some parameters.
<?php use function ICanBoogie\Service\ref; $reference = ref('hello'); echo $reference("Olivier"); // Hello Olivier!
Of course, non-callable services can also be referenced, in which case the method
used to obtain the service:
<?php use function ICanBoogie\Service\ref; $reference = ref('my_non_callable_service'); $service = $reference->resolve(); $service->do_something(); # The reference forwards calls to the service, but that's a secret $reference->do_something();
The service provider
The service provider is created during the application boot event, and acts as a proxy for the
dependency injection container, which is only created when a reference needs to be resolved, or when
the container is explicitly required through
Obtaining services bound to the application
Usually, ICanBoogie's components add getters to the
ICanBoogie\Application instance through the
prototype system, which means the initial request is accessed with
the session with
$app->session. In order to have these available to the container, an extension
automatically add definitions for them. Now the session can also be obtained with
Services are defined using
services.yml files in
config folders. They are collected when it's time
to create the container, just like regular configuration files.
The following example is a sample of the services defined for my blog. You'll notice the
service, which is actually bound to the
services: # Event event_hook.on_rescue_exception: class: App\Application\Handler\RescueExceptionHandler arguments: - "@renderer" # Controller controller.page: class: App\Presentation\Controller\PageController
Services can be defined using Symfony's Dependency Injection component and only super sexy
services are bound to the