13

I'm new to services (and drupal 8!) and trying to figure out services. I think perhaps I'm just doing the create in an outdated way. What I want do is make my 'hello generator' a service and call it in another controller with the following:

DBController.php

namespace Drupal\db\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\db\DbServices\HelloGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;


class DBController extends ControllerBase
{
private $helloGenerator;

public function __construct(HelloGenerator $x) {
    $this->helloGenerator = $x;
}
public function say($count) {
    $hello = $this->helloGenerator->getHello($count);

    return new Response($hello);
}

public static function create(ContainerInterface $container) {
    $x = $container->get('db.hello_generator');
    return new static ($x);
}
}

HellGenerator.php

namespace Drupal\db\DbServices;

class HelloGenerator {

public function getHello($count) {
    $foo = 4 + 4 + 4;
    return $foo . ' ' . $count;
}

}

db.services.yml

services:
  db.hello_generator:
     class: Drupal\db\DbServices\HelloGenerator

db.db_says:
  path: /db/says/{count}
  defaults:
    _controller: '\Drupal\db\Controller\DBController::say'
  requirements:
    _permission: 'access content'
1
  • You can follow document. It's correct way to call a service in a controller
    – MrD
    Aug 5, 2016 at 17:46

1 Answer 1

26

There are 3 questions here:

  1. How to create a controller?
  2. How to create a service?
  3. How to use services in a controller?

1. Create a controller

1.1 Add a controller class - you did it. For others see Drupal documentation

1.2 Add a routing file - it looks like this is missing in your code:

my_module.routing.yml

my_module.my_route_name:
  path: '/my/path'
  defaults:
    _controller: '\Drupal\my_module\Controller\MyController::myAction'
  requirements:
    _permission: 'access content'

see Drupal documentation

2. Create a service

2.1 Add a service class - you did it.

2.2 Add a routing file - you did it although it contains extra code that belongs to the routing file. This is all you need:

my_module.services.yml

services:
  my_module.my_service:
    class: Drupal\my_module\Service\MyService

see Drupal documentation

3. Use services in a controller

You did it. Here's a reference for others:

3.1 Override the create() method

The controller class inherits this method from class ControllerBase. Its role is to create the controller object. Watch the method argument: it is passed the services container. Extract the services you need and pass them to the constructor:

public static function create(ContainerInterface $container) {
    $my_service = $container->get('my_module.my_service');
    $other_service = $container->get('other_service');

    return new static($my_service, $other_service);
}

3.2 Initialise services in __construct()

public function __construct($my_service, $other_service)
{
    $this->my_service = $my_service;
    $this->other_service = $other_service;
}

3.3 Start using the services

5
  • 6
    I wish the official documentation was more in this style, or at least had a few overview articles that was. Short and concise with a generic example easily translated to the real application.
    – Nicolaj
    Feb 1, 2018 at 9:59
  • A do not forget: use Symfony\Component\DependencyInjection\ContainerInterface; in controller class
    – Atep
    Feb 27, 2020 at 8:02
  • While I totally agree with @Nicolaj's comment, this isn't working for me...and I'm not even trying to use a custom service! All I want to do is create a class member variable that holds a static database connection object. I'm used to using systems where connection pooling and never creating more connections than you need is the norm. So how would I implement something similar in a Drupal controller/form?
    – Kenny83
    Apr 8, 2020 at 15:11
  • You might want to open another question @Kenny83, but have you looked at api.drupal.org/api/drupal/core%21lib%21Drupal.php/function/… ? With that you can do something like this: gist.github.com/glaux/f4f1517563ddb57fb98b9213802c1569
    – Nicolaj
    Apr 8, 2020 at 15:22
  • @Nicolaj LOL thanks for pointing out the bleedingly-obvious mate :P I'm well-aware of the core database service and that's what I'm trying to return from my create() method. I suppose you wouldn't have said that though if I hadn't missed something else that should have been obvious...I guess that service does pool connection objects?
    – Kenny83
    Apr 8, 2020 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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