Wednesday 1 May 2019

How to create a Drupal 8 service in your next module

Hi Everybody,

This is after long time, i am writing this blog in Drupal 8. In this article, we are going to see how we could create basically the simplest Drupal 8 service and then we are going to inject some stuff to it in order to see also how Dependency injection works.

As always you will get the full code example, wrapped in its own module in order to be easier for you to go for it, test it, change it or just compare it with the version that you are going to build.

Let's see first how we may declare a service class inside of our Drupal 8 module. Basically, it is a normal PHP class, that is supposed in the general case to be located in your module under the /src folder. Let's create a dummy class and give it some general methods. Our class PHP file is called CowService.php and contains this:

<?php

namespace Drupal\drupalup_service;

/**
 * CowService is a simple exampe of a Drupal 8 service.
 */
class CowService {

  private $sounds = ["looO", 'mooO'];

  /**
   * Returns a cow sound.
   */
  public function saySomething() {
    return $this->sounds[array_rand($this->sounds)];
  }

  /**
   * Real photo of our cow.
   */
  public function howDoYouLookLike() {
    return print_r('
           (    )
            (oo)
   )\.-----/(O O)
  # ;       / u
    (  .   |} )
     |/ `.;|/;
     "     " "
     ', FALSE);
  }
}

Our silly class has it's namespace defined and the other part is a quite normal PHP class.

The next thing we want to do is to declare our class as a service. We are doing it with the help of the *.services.yml located in your module. So in our case, we created a file called drupalup_service.services.yml and the declaration could be something like this:

services:
    drupalup_service.cow:
        class: Drupal\drupalup_service\CowService

And that's basically the simplest service on earth. It is a good idea to have them namespaced with your module name and the class declaration simply follows the namespace, declared in your service file + the name of the class.

That's very cool. In order to wrap it up - we just need to create a module around it, simply create an info file and it should work (here is the final version of our module).

 Let's go ahead and test it with the help of the devel module and the "Execute PHP Code" page that it has. We simply go under /devel/php and we make sure that before that we have activated our newly created module. In order to instantiate our service, we only have to use in the general case the following code and we can directly make it do something:

$our_service = \Drupal::service('drupalup_service.cow');
$our_service-> howDoYouLookLike();


And here is the output and how our cattle looks like:



You could just stop here and be completely happy with the things you've learned, but if you want to learn something about these fairytale creatures that are coming from the fog that are using Dependency Injection - keep reading.

Let's modify a bit our code in order to inject the current_user service into our own service and use it to say that we (the current logged in user) is the owner of the cowy. Here is the modified service declaration, essentially we are just passing the service machine name as an argument, starting with @.

services:
    drupalup_service.cow:
        class: Drupal\drupalup_service\CowService
        arguments: ['@current_user']
and the change to our class that will enable us to catch the injected service object:

<?php

namespace Drupal\drupalup_service;

use Drupal\Core\Session\AccountInterface;

/**
 * CowService is a simple exampe of a Drupal 8 service.
 */
class CowService {

  private $currentUser;
  private $sounds = ["looO", 'mooO'];

  /**
   * Part of the DependencyInjection magic happening here.
   */
  public function __construct(AccountInterface $currentUser) {
    $this->currentUser = $currentUser;
  }

  /**
   * Returns a a Drupal user as an owner.
   */
  public function whoIsYourOwner() {
    return $this->currentUser->getDisplayName();
  }

  /**
   * Returns a cow sound.
   */
  public function saySomething() {
    return $this->sounds[array_rand($this->sounds)];
  }

  /**
   * Real photo of our cow.
   */
  public function howDoYouLookLike() {
    return print_r('
           (    )
            (oo)
   )\.-----/(O O)
  # ;       / u
    (  .   |} )
     |/ `.;|/;
     "     " "
     ', FALSE);
  }
}

The difference is that we declared the __construct function, where we are getting the injected service and we are saving it into our private variable, called currentUser. Then we are simply using the method getDisplayName of the service to show the current logged in user, who is supposed to be the owner of the cowy. Underneath you will see the output that we are getting from our newly declared method:



















Thanks for reading and don't forget to have fun with Drupal module development.

No comments:

Post a Comment