8

In Symfony 2 when defining a service it is possible to inject configuration parameters by referencing them with %parameter.name% strings. For example:

services:
  app.mailer:
    class:        AppBundle\Mailer
    arguments:    ['%app.mailer.transport%']

But what is the correct Drupal 8 approach to injecting configuration values into services? Of course I don't want to use \Drupal::config() inside a service class. Passing configuration values each time a service is referenced does not make much sense either.

I know that I can inject the config service itself and then get configuration values from it, but that looks a bit crappy as my service itself has know how to read data from configuration service. For example:

# Yaml service configuration
services:
  app.mailer:
    class:        mail_module\Mailer
    arguments:    ['@config.factory']

PHP

<?php
class Mailer {
  public function __construct($config) {
    $this->mailTransport = $config->get('mail.config')->get('transport');
  }
}

Is there any other way to do this?

  • 1
    The D8 approach is to use the @config.factory service to get configuration from the configuration service. This is because the configuration service could be overridden and not necessarily getting its configuration values from the same place. – mradcliffe Mar 8 '16 at 17:04
7

You can use a factory for your app.mailer service. The factory take cares of retrieving the configuration for the service. The service can stay decoupled from the configuration service and does not need to know how the config parameters are named.

services:
  app.mailer:
    class:       Drupal/mail_module/Mailer
    factory:      Drupal/mail_module/MailerFactory:create
    arguments:    ['@config.factory']


class MailerFactory {
  static function create($config) {
    return new Mailer($config->get('mail.config')->get('transport'));
  }
}

class Mailer {
  public function __construct($transport) {
    $this->mailTransport = $transport;
  }
}
| improve this answer | |
3

That's the way to do it. Configuration can change at runtime, the service definition is usually persisted and rebulding it is expensive. Assuming it is configuration that you want users to change.

If it is not, then you can use parameters, just like the symfony example. Then you can put your configuration in services.yml in sites/default. But you can only change it by changing the code and rebuilding the container.

| improve this answer | |
  • OK, so this basically means that a service needs to know how config parameters are named in order to obtain them from the config factory service. A bit awkward and makes testing more complicated. Is there some kind of a config factory stub for testing purpose? – SiliconMind Mar 8 '16 at 19:32
3

You can use a factory or configurator service that is aware of how the config factory works etc, that keeps your service decoupled from the config factory. The HTTP client in core has a configurator if you need an example. See https://symfony.com/doc/current/service_container/configurators.html#using-the-configurator for docs.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.