The ABC Manager 6 [Service Container](https://docs.angrybytes.com/p/abc-manager/6.0/docs/container/introduction/index.html) is a
powerful component adopting the Dependency Injection concept and will hold almost all knowledge about your
bundle components and their parameters.
Almost all of the ABC Manager 6 core *bundles* already register their components as **services** in the
service container, as well as the **parameters** used by them. In addition to that, we have added
some features on top of the service container to add more flexibility when developing applications.
In this demonstration, we will not lay the focus on the service container itself, since there is already more than
enough proper [reading material](http://symfony.com/doc/current/book/service_container.html) out there.
Instead, we will focus on some of the additional features that we've added:
* Automatic conversion of `application` and `project` YAML configuration parameters into service container parameters.
* The ability to define a single service definition for each applications uses the bundle (via [Kernel registration](https://docs.angrybytes.com/p/abc-manager/6.0/docs/kernel/introduction/index.html)), thus
making them **application aware**.
### YAML Configuration to Service Container Parameters
---
Before ABC Manager 6, you had fewer possibilities to expose application or project wide configuration values to your
application logic. YAML configuration, placed inside the `sitebased` or `site` YAML files needed to be retrieved
directly from inside your components and there was no way to automatically inject configuration values into components.
In ABC Manager 6, having the service container and using dependency injection, it becomes fairly easy to inject
these values into your components, by defining them as service container **parameters** in the `services.yml` file on a
per bundle basis.
In addition to that we will parse the YAML configuration files and inject the configuration nodes/values as parameters into
the service container when [compiling the container](http://symfony.com/doc/current/components/dependency_injection/compilation.html).
Read More about YAML to parameter conversion [here](https://docs.angrybytes.com/p/abc-manager/6.0/docs/container/configuration/index.html#configuration-to-container-parameters).
#### YAML Configuration
To demonstrate this, a dummy node has been added to the `demo` application's YAML configuration:
```yml
### file: applications/demo/applications/Resources/config/config.yml
url: 'https://demo.abc-demo.test'
```
#### Service Definition
By defining an [application aware parameter](https://docs.angrybytes.com/p/abc-manager/6.0/docs/container/application/index.html)
in the `Demo\ServiceContainerBundle` bundle, we are now able to automatically inject the `
` configuration value as
a service container parameter into components.
Keep the following rules in mind:
* Container parameters derived from `applications//Resources/config/config.yml` config values will be
prefixed with the application id: "`[application-id].`".
* Container parameters derived from `project/Resources/config/config.yml` config values will be prefixed with "`abc.`".
* Nested YAML configuration values are imploded and separated by a dot [`.`] value.
* Example:
```yml
foo:
bar: 'baz'
```
equals `foo.bar: 'baz'`.
The `services-application.yml` file inside the `ServiceContainerBundle` bundle registers a parameter with the same
name used in the YAML configuration and injects the parameter value into a service definition:
```yaml
# file: src/Demo/ServiceContainerBundle/Resources/config/services-application.yml
parameters:
# Overwritable by application configuration node: ...
$application.url: ''
services:
# Container demo component
$application.container:
class: Demo\ServiceContainerBundle\Container
calls:
# Inject the application url parameter
- [set, [%$application.url%]]
# By using $application, a service or parameter is created for 'every' application that registers this bundle
```
By fetching the service `$application.container` for this application, with application id "`demo`", we can now
retrieve the `url` value derived from the configuration and use it to our liking:
The `` configured for this application is: https://demo.abc-demo.test
```php
// file: src/Demo/PublicationBundle/Controller/Demo.php:#27
/**
* Demo the service container
*
* @return Response
**/
public function serviceContainerAction()
{
// Retrieve the url via the contaioner service
// Uses "Abc\HttpBundle\Controller\ContainerAware::get()" to retrieve a service from the container
$appUrl = $this->get('demo.container')->getValue();
...
}
```
We have now successfully converted, used and displayed a service container parameter that has been derived from
the YAML configuration.
### Application Aware Services
---
In addition to regular services, defined in `services.yml` files, ABC Manager 6 allows bundles to register
container services and parameters that will automatically be registered inside the container during compilation
**for each application** the bundle is registered for in the project Kernel. These application aware services are registered
in a file called `services-application.yml` and are automatically picked up by our core.
These services especially come in handy when they act upon any given application, not for one application in particular.
For example, the ABC Manager dispatcher, retrieved from the service container in every front controller (`index.php`)
file does this. The service definition is registered for each application:
```yaml
# file: vendor/angrybytes/abc-maanger/src/HttpBundle/Resources/config/services-application.yml
services:
# Dispatcher component for every application
$application.dispatcher:
class: Abc\HttpBundle\Dispatcher\Routed
```
The application aware service files are be parsed by a [Compiler Pass](http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html)
during container compilation and are registered inside the container for every application added in the project Kernel
(and the `cms` application). For every application, the `$application` part gets replaced with the actual application id
to create a new, unique, service id for that application.
To demonstrate this effect, we will register an application aware service, inject the current (dispatched) application
instance into the service (made available by the ABC core under id `@$application`) and retrieve some values from it.
First, we register an application aware service:
```yaml
# file: src/Demo/ServiceContainerBundle/Resources/config/services-application.yml
services:
# Container Demonstration Service
$application.app_aware_service:
class: Demo\ServiceContainerBundle\Container
calls:
- [setValue, [@$application]]
```
And now we can retrieve this service in our application logic based on a given application id and retrieve its values:
**Demo App**
Some application properties:
* The application has id: `demo`
* The application's frontend url is: https://acc-abc-demo.angrybytes.com
* The applicaiton's webroot is: `/var/www/html/project/includes/../../applications/demo/public`
```php
// file: src/Demo/PublicationBundle/Controller/Demo.php:#27
/**
* Demo the service container
*
* @return Response
**/
public function serviceContainerAction()
{
// Second demo; retrieve an application aware service
$dispatchedApp = $this->get('demo.app_aware_service');
// Render template w/ $dispatchedApp
}
```
```twig
# file: service-container.html.twig
{{ dispatchedApp.getName() }}
Some application properties:
* The application has id: {{ dispatchedApp.getId() }}
* The application's frontend url is: {{ dispatchedApp.getUrl() }}
* The applicaiton's webroot is: {{ dispatchedApp.getDirectoryLayout().getPublic() }}
```
This demonstrates how generic services are created that are able to work on any given ABC Application.