Skip to content

Commit e29da51

Browse files
Updated slides and readme file.
1 parent 4ae529c commit e29da51

2 files changed

Lines changed: 101 additions & 59 deletions

File tree

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,17 @@
11
# An Introduction To Services In Drupal
2-
A talk going through the Drupal services system.
2+
A talk going through the Drupal services system.
3+
4+
## Slides
5+
6+
You can view the slides in a number of ways:
7+
8+
- HTML (download this repo open the file `dist/slides.html`)
9+
- [PDF](https://github.com/hashbangcode/drupal-services-talk/blob/main/dist/slides.pdf)
10+
- [PPTX](https://github.com/hashbangcode/drupal-services-talk/blob/main/dist/slides.pptx)
11+
12+
## Resources
13+
14+
- [Drupal Services Examples](https://github.com/hashbangcode/drupal_services_example)
15+
- [Drupal 9: An Introduction To Services And Dependency Injection](https://www.hashbangcode.com/article/drupal-9-introduction-services-and-dependency-injection)
16+
- [Drupal 9: Extending Drupal Base Classes Without Overriding Constructors](https://www.hashbangcode.com/article/drupal-9-extending-drupal-base-classes-without-overriding-constructors)
17+
- []()

src/slides.md

Lines changed: 85 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ This talk will assume you have some understanding of PHP and OOP, but if you get
7676
- They are an essential part of Drupal.
7777
- If you are going to build or maintain a module then you will use services.
7878
- I quite like back to basics talks.
79-
- Coming soon are service hooks, meaning that we will soon lose hooks and need to use services instead.
79+
- Coming soon are service hooks. We will soon lose some hooks and need to use service based hooks instead.
8080
-->
8181

8282
---
@@ -85,43 +85,31 @@ This talk will assume you have some understanding of PHP and OOP, but if you get
8585

8686
- Used in all parts of Drupal and many modules.
8787
* Built on the <strong>Symfony Service Container</strong> system.
88+
8889
* A service describes an object in Drupal.
90+
8991
* Dependency injection is used to inject services into other services.
90-
* Forms, controllers, and plugins have services built in.
92+
9193
* Simple to use and powerful.
9294

9395
---
9496

95-
```php
96-
\Drupal::service('thing');
97-
```
97+
# Using A Service
9898

9999
---
100100

101-
## What Services Exist?
101+
## Using A Service
102102

103-
- Lots!
103+
- Services can be accessed via the Drupal object.
104104

105-
```bash
106-
drush eval "print_r(\Drupal::getContainer()->getServiceIds());"
105+
```php
106+
$serviceObject = \Drupal::service('thing');
107107
```
108108

109-
- Prints a list of over 600 services.
110-
- Most are in the form `date.formatter`.
111-
- Some are in the form `Drupal\Core\Datetime\DateFormatterInterface`, and are used in autoloading.
112-
113-
<!--
114-
The simple version of date.formatter is what is normal in Drupal.
115-
The interface form is used for autoloading.
116-
-->
117-
---
118-
119-
# Using A Service
120-
121109
---
122110
## Using A Service
123111

124-
- Grab the service.
112+
- To use a service, pick the service you need.
125113
- Use it.
126114

127115
```php
@@ -143,11 +131,30 @@ $normalPath = \Drupal::service('path_alias.manager')->getPathByAlias('somepath')
143131

144132
---
145133

134+
## What Services Exist?
135+
136+
- There are lots!
137+
138+
```bash
139+
drush eval "print_r(\Drupal::getContainer()->getServiceIds());"
140+
```
141+
142+
- Prints a list of over 600 services in Drupal core.
143+
- Most are in the form `date.formatter`.
144+
- Some are in the form `Drupal\Core\Datetime\DateFormatterInterface`, and are used in autoloading.
145+
146+
<!--
147+
The simple version of date.formatter is what is normal in Drupal.
148+
The interface form is used for autoloading.
149+
-->
150+
---
151+
146152
## Using A Service
147153

148154
- However! Most of the time you don't want to be using `\Drupal::service()`.
149-
- Drupal will inject the services you need into your service.
150-
- This is called <strong>dependency injection</strong>.
155+
* Unless you are running code in a hook you should be injecting services into your own code.
156+
* Drupal will handle what services are needed to create your needed service.
157+
* This is called <strong>dependency injection</strong>.
151158

152159
---
153160

@@ -161,9 +168,6 @@ A quick introduction.
161168

162169
Dependecy injection sounds complicated, but its just the practice of <strong>injecting the things the object needs</strong>, instead of <strong>baking them into the class</strong>.
163170

164-
<!--
165-
Some OOP wording here. Make sure this is clear.
166-
-->
167171
---
168172

169173
## Dependency Injection
@@ -179,6 +183,7 @@ class Page {
179183
}
180184
$page = new Page();
181185
```
186+
182187
- What happens if you want to change the credentials? Or change the database itself?
183188
- You would need to edit the class.
184189
<!--
@@ -205,21 +210,23 @@ $page = new Page($database);
205210
Dependency Inversion principle.
206211
-->
207212
---
213+
208214
## Dependency Injection
209-
- Drupal handles all the dependency creation.
210-
- It will create services with all of the required objects in place.
215+
216+
- Drupal handles all the dependency creation automatically.
217+
- It will create services with all of the required objects.
211218
- All we need to do is ask for our service.
219+
212220
---
213221

214222
## Why Use Dependency Injection In Drupal?
215223

216-
Let's try to create the `path_alias.manager` service to translate a path <em>without</em> using Drupal's dependency injection system.
224+
Let's try to create the `path_alias.manager` service to translate a path <em>without</em> using Drupal's automatic dependency injection system.
217225

218226
---
219227

220228
The `path_alias.manager` service wraps the `\Drupal\path_alias\AliasManager` class.
221229

222-
223230
```php
224231
use Drupal\path_alias\AliasManager;
225232

@@ -302,7 +309,7 @@ use Drupal\Core\Database\Database;
302309
$connection = Database::getConnection();
303310
$pathAliasRepository = new AliasRepository($connection);
304311

305-
$cid = 'path_alias_whitelist';
312+
$cid = 'path_alias_prefix_list';
306313
$pathPrefixes = new AliasPrefixList($cid, $cache, $lock, $state, $alias_repository);
307314

308315
$aliasManager = new AliasManager($pathAliasRepository, $pathPrefixes,
@@ -322,7 +329,7 @@ use Drupal\Core\Site\Settings;
322329
$connection = Database::getConnection();
323330
$pathAliasRepository = new AliasRepository($connection);
324331

325-
$cid = 'path_alias_whitelist';
332+
$cid = 'path_alias_prefix_list';
326333

327334
$settings = Settings::getInstance();
328335
$default_bin_backends = ['bootstrap' => 'cache.backend.chainedfast'];
@@ -335,7 +342,6 @@ $aliasManager = new AliasManager($pathAliasRepository, $pathPrefixes,
335342
$languageManager, $cache, $time);
336343
```
337344
<!--
338-
The `$cache` property is an object of type `\Drupal\Core\Cache\CacheFactoryInterface`, so we can use `\Drupal\Core\Cache\CacheFactory` to create this. We first need to create a `\Drupal\Core\Site\Settings` object to create that.
339345
340346
We have now made several assumptions about our settings, the type of cache we will use, where the cache bin is stored.
341347
This has created very brittle code that is prone to breakage.
@@ -366,7 +372,7 @@ Seems easier, right?
366372

367373
## Creating Services
368374

369-
- All services are defined in a `[module].services.yml` file in your module directory.
375+
- Custom services are defined in a `[module].services.yml` file in your module directory.
370376

371377
```yml
372378
services:
@@ -524,15 +530,17 @@ services:
524530
- Create your class as normal. The interfaces you nominate will be translated into services and automatically injected into your constructor.
525531

526532
```php
527-
<?php
528-
529533
namespace Drupal\services_autowire_example;
530534
531-
use Drupal\Component\Serialization\SerializationInterface;
535+
use Drupal\Core\Password\PasswordGeneratorInterface;
532536
533537
class AutowireExample implements AutowireExampleInterface {
534538
535-
public function __construct(protected SerializationInterface $serializer) {
539+
public function __construct(protected PasswordGeneratorInterface $passwordGenerator) {
540+
}
541+
542+
public function generate12CharacterPassword():string {
543+
return $this->passwordGenerator->generate(12);
536544
}
537545
}
538546
```
@@ -546,7 +554,7 @@ class AutowireExample implements AutowireExampleInterface {
546554
## Controllers And Forms
547555

548556
- Some types of Drupal object (especially Controllers and Forms) don't use `*.services.yml` files.
549-
* Instead they implement
557+
- Instead they implement
550558
```
551559
\Drupal\Core\DependencyInjection\ContainerInjectionInterface
552560
```
@@ -562,18 +570,20 @@ class AutowireExample implements AutowireExampleInterface {
562570
```php
563571
class ControllerExample extends ControllerBase {
564572
565-
protected $dateFormatter;
573+
protected $passwordGenerator;
566574
567575
public static function create(ContainerInterface $container) {
568576
$instance = new static();
569-
$instance->dateFormatter = $container->get('date.formatter');
577+
$instance->passwordGenerator = $container->get('password_generator');
570578
return $instance;
571579
}
572580
573581
/// ..
574582
}
575583
```
576-
584+
<!--
585+
The static() here is a reference to the current class. This calls the constructor but you probably don't need to define the controller.
586+
-->
577587
---
578588
## Plugins
579589

@@ -586,6 +596,23 @@ class ControllerExample extends ControllerBase {
586596
<!--
587597
Plugins work in the same way, but plugins will have additional arguments that need to be passed upstream.
588598
-->
599+
---
600+
601+
## Plugins
602+
603+
- The plugin controller does have a function in this instance.
604+
605+
```php
606+
public static function create(ContainerInterface $container,
607+
array $configuration,
608+
$plugin_id,
609+
$plugin_definition
610+
) {
611+
$instance = new static($configuration, $plugin_id, $plugin_definition);
612+
$instance->passwordGenerator = $container->get('password_generator');
613+
return $instance;
614+
}
615+
```
589616

590617
---
591618

@@ -606,6 +633,7 @@ Plugins work in the same way, but plugins will have additional arguments that ne
606633
<!--
607634
This isn't a rug pull. All your normal hooks will work for the time being.
608635
-->
636+
609637
---
610638

611639
## Hook Service Classes
@@ -677,7 +705,7 @@ The aim is to allow low level hooks that have no dependencies to operate as they
677705
## Tagged Services - Events
678706

679707
- The simplest tagged service is the event handler.
680-
- This service will be triggered when .
708+
- This service will be triggered when events happen.
681709

682710
```yml
683711
services:
@@ -715,7 +743,7 @@ class EventListenerService implements EventSubscriberInterface {
715743
<!-- _footer: "" -->
716744
## Tagged Services - Autoconfigure
717745

718-
- Use the `autoconfigure: true` directive to automatically tag classes that implement the `Symfony\Component\EventDispatcher\EventSubscriberInterface` interface
746+
- Use the `autoconfigure: true` directive to automatically tag classes.
719747

720748
```yml
721749
services:
@@ -724,6 +752,7 @@ services:
724752
services_autoconfigure_example.autoconfigured_service:
725753
class: \Drupal\services_autoconfigure_example\EventSubscriber\AutoconfiguredService
726754
```
755+
- For events, Drupal looks for services that extend <p class="small-text">\Symfony\Component\EventDispatcher\EventSubscriberInterface</p>
727756

728757
---
729758

@@ -744,7 +773,7 @@ services:
744773

745774
- Don't "hand off" dependencies to internal classes, use additional services.
746775
* Consider not creating a service if the class has no dependencies.
747-
* If you need to alter the class at runtime then make the service to allow Drupal to do that.
776+
* If you need to alter the class at runtime then make a service to allow Drupal to do that.
748777

749778
---
750779

@@ -782,7 +811,7 @@ services:
782811
decorates: password_generator
783812
```
784813
<!--
785-
Here, we are decorating the serialization.json and creating our own service called services_decorator_example.decorated_json.
814+
Here, we are decorating the password_generator and creating our own service called services_decorator_example.decorated_password_generator.
786815
The critical thing is that the existing service class still exists. The new service just extends that.
787816
-->
788817

@@ -800,7 +829,7 @@ namespace Drupal\services_decorator_example;
800829
use Drupal\Core\Password\DefaultPasswordGenerator;
801830
802831
/**
803-
* Decorates the Json class.
832+
* Decorates the DefaultPasswordGenerator class.
804833
*/
805834
class DecoratedPasswordGenerator extends DefaultPasswordGenerator {
806835
@@ -815,11 +844,11 @@ class DecoratedPasswordGenerator extends DefaultPasswordGenerator {
815844
## Altering Services: Altering
816845

817846
- Override the serivce completely and replace it with your own.
818-
- Create a class that has the name `[ModuleName]ServiceProvider`, which extends the class `\Drupal\Core\DependencyInjection\ServiceProviderBase`.
819-
- Drupal will pick up this class and run the `register()` and `alter()` methods.
847+
* Create a class that has the name `[ModuleName]ServiceProvider`, which extends the class <p class="small-text">\Drupal\Core\DependencyInjection\ServiceProviderBase</p>
848+
* Drupal will pick up this class and run the `register()` and `alter()` methods.
820849

821850
<!--
822-
Use register() to register a new service in Drupal. Useful for highly dynamic services where you want to automatically discover your services at run time.
851+
Use register() to register a new service in Drupal. Useful for highly dynamic services where you want to automatically create your services at run time.
823852

824853
Use alter() to alter the service registry and change any registered service in the site.
825854
-->
@@ -859,13 +888,11 @@ Here, we are altering the joke_api.joke service to replace it with our a stub se
859888

860889
There's much more to Drupal services, try looking up
861890

862-
- Tagged services
863-
- Event handlers
864-
- Access control
865-
- Logging
866-
- Lazy
867-
- Public
868-
- alias
891+
- Access control services
892+
- Factories
893+
- Lazy services
894+
- Public and private services
895+
- Service aliases
869896
---
870897
<!-- _footer: "" -->
871898
## Resources

0 commit comments

Comments
 (0)