24

There are 3 questions here: How to create a controller? How to create a service? 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' ...


22

In a controller you inject services by using the service container. For example ModuleHandler: namespace Drupal\mymodule\Controller; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; class MyController extends ControllerBase { /** * The module ...


20

The controller base class provides the method entityTypeManager() which gets the service with the same name from the container the first time you use it. You can use this service to get the node storage: $node_storage = $this->entityTypeManager()->getStorage('node'); and then load the node: $node = $node_storage->load($nid);


18

Take the BlockLibraryController class as example; it extends the same class as your controller. You define: A static and public create() method that gets the values from the dependency container, and creates a new object of your class A class constructor that saves the values passed from the previous method in object properties A set of object properties ...


18

What you are missing is to implement \Drupal\Core\Plugin\ContainerFactoryPluginInterface, which defines the create() method. See \Drupal\file\Plugin\Field\FieldWidget\FileWidget for an example.


17

DI requires a bit more effort than that - you haven't told the system about your class; the DI container doesn't know that you've called new MyClass(), and it can't get involved. You need to create a Service, which you can make depend on other available services, instances of which will be passed to your class using the static create method pattern you're ...


15

For future reference, from the link by @Kevin: The key to making plugins use dependency injection is to implement the ContainerFactoryPluginInterface. When plugins are created, the code first checks if the plugin implements this interface. If it does, it uses the create() and __construct() pattern, if not, it uses just the __construct() pattern. - ...


13

This is how I injected the entity type manager to load nodes into a block (where the nodes to load didn't come from the block context): <?php namespace Drupal\MYMODULE\Plugin\Block; use Drupal\Core\Block\BlockBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Entity\...


11

I accidentally declared the $custom_manager property of my class as private instead of protected, and that's why I was unable to access the custom manager object in the form submission method. Whoops! MPD's answer is theoretically correct though, as class requiring to access services do need to implement the ContainerInjectionInterface class. Worth noting ...


10

If you are extending FormBase you can use create to inject dependencies. In this case what I think you want is the entity_type.manager service and file.usage. /** * Class constructor. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, FileUsageInterface $file_usage) { $this->entityTypeManager = $...


9

create() is a factory method for dependency injection. Plugins which implement ContainerFactoryPluginInterface are instantiated by create() of the plugin class: ContainerFactory::createInstance public function createInstance($plugin_id, array $configuration = []) { ... // If the plugin provides a factory method, pass the container to it. if (...


8

You are on the right track! Your tests should also never depend on calling out to external services. You should build a list of responses and scenarios you expect from the external service and ensure your tests are using your deterministic source data every time. In your test you need to either provide instances of your dependencies or mocked versions of ...


8

In Drupal 8, you should always use dependency injection within the context of classes. However, if you create a custom service, you don't have to manually implement the ContainerInjectionInterface. Instead, you define your service and the arguments for the constructor within your module's example_service.services.yml file (read more about .services.yml ...


7

You can't inject Drupal\Core\Database\Database, it's a container of static functions, constants, & variables for core database functions. If you'd like to inject the Connection object, that is be possible, and is more like something you want (unless you have scenario where setting.php is dynamic an all possible values of $schema can't be known). You ...


7

You should use entity_type_manage to get the user storage. Something like this: <?php namespace Drupal\country_selector\Plugin\Block; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Block\BlockBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\user\...


7

The standard way to inject services in other services is passing dependencies directly through the constructor: mymodule.services.yml: services: mymodule.foo_service: class: Drupal\mymodule\FooService arguments: ['@current_user'] While you can define a factory method in *.services.yml, see https://symfony.com/doc/current/service_container/...


6

\Drupal::service('config.factory') and \Drupal::configFactory() are equivalent; the second is just shorter. There are many, many services provided by core, and only a few of them have a dedicated method. You can get a list of core services on the core.services.yml page. Note that this is not all services that core offers, for example, there are more ...


6

The service you need is entity_type.manager: .services.yml services: hsbxl_members.membership: class: Drupal\hsbxl_members\MembershipService arguments: ['@entity_type.manager'] MembershipService.php namespace Drupal\hsbxl_members; use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Class MembershipService. */ class MembershipService { ...


6

It's the static method Drupal core uses to create the plugin. (See, for example, the documentation for SystemMenuBlock::create().) Drupal core doesn't instantiate a plugin with new PluginClass(), but PluginClass::create(). This allows the class implementing the plugin to return an instance previously created. The other pro is that the signature of the ...


6

Add the class to mymodule.services.yml and inject the core services there: mymodule.services.yml services: mymodule.book: class: Drupal\mymodule\Book arguments: ['@entity.query', '@entity_type.manager'] Then use the service in procedural code: \Drupal::service('mymodule.book')->read($cid)


5

You can check how the dependency injection works in general in this documentation. https://www.drupal.org/docs/8/api/services-and-dependency-injection/dependency-injection-for-a-form The parts that you need are: Use statement - use Symfony\Component\DependencyInjection\ContainerInterface; Class property - here we are going to store the whole \Drupal::...


5

As commented on another answer, the answer here is probably, you can't. The database API isn't fully converted to use services. I tried to do it for quite some time, in https://www.drupal.org/node/1811730, but didn't succeed and neither did others. So, for now, you need to use the static methods. The best you can do is wrap it in a method or another ...


5

Not sure which part exactly is unclear. There are lots of examples in core.services.yaml that inject the config.factory service to read a configuration object, for example this: diff.formatter: class: Drupal\Core\Diff\DiffFormatter arguments: ['@config.factory'] The constructor for that then looks like this: /** * Creates a DiffFormatter to render ...


5

Yes, for procedural code in hooks you have to use the static service container wrapper \Drupal. Either to get a service or to use one of the predefined static functions. See for example: shortcut.install /** * Implements hook_install(). */ function shortcut_install() { // Theme settings are not configuration entities and cannot depend on modules // ...


5

Both the examples are wrong. A service doesn't normally implement the ContainerInjectionInterface interface. It can be implemented by other classes, for example the AggregatorController class, which is not a service, since it is not listed in the aggregator.services.yml file of the Aggregator module. As described in Services and Dependency Injection ...


5

Classes aren't naturally aware of the container, you have to implement them in such a way that they are. The most common approach for controllers is to extend Drupal\Core\Controller\ControllerBase, and override the create method, e.g. use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Session\AccountProxyInterface; use Symfony\Component\...


4

You don't need to define your FieldFormatter as a service. FieldFormatters are instantiated inside the FormatterPluginManager's createInstance method (FormatterPluginManager::createInstance) which calls a create method on the formatter plugin object, passing a $container object as a parameter. But this happens only if your FieldFormatter implements the \...


4

Not certain, but it sounds like your files may not be in the correct places based on your description. The services.yml should be in the root of your module, not in a sub folder. Also, your service classes should be in a /src/ folder. It would be okay to have them in a /src/services folder if you want, but module namespaces in drupal start in the module's ...


4

I have few thoughts about this situation: Controllers should not contain business logic, services should. Therefor unit testing a controller is not a good idea in the first place. If you are unit testing your controllers "getResource" method, why do mock the controller itself? You should mock the HttpClient. (that's the strong part of DI) First you mock ...


4

You will need to implement ContainerFactoryPluginInterface in order to use dependency injection in your class. Include use Drupal\Core\Plugin\ContainerFactoryPluginInterface; and implement the interface so it looks like: class XoisSicSelect extends WidgetBase implements ContainerFactoryPluginInterface { .... } You will also need to make sure your ...


Only top voted, non community-wiki answers of a minimum length are eligible