0

My controller class holds some not-so-easy logic to receive some data from a route parameter I need in a block plugin. As this block will only be rendered on this specific route, I would like to simply get the route controller route with this block which would receive its data from the controller.

Is there any way to get the controller class from any of the services like current_route_match?
I can get the route object or the route name, but I didn't find a way to get the controller class.

4
  • 7
    Why don't you refactor your not so easy logic into a helper service class, and then call the helper service from controller and block instead? Sometimes refactoring is needed to prevent code smell. Define your own service and inject the route into the service
    – Hudri
    Commented Nov 24, 2020 at 11:31
  • You can also instantiate the block plugin from your controller and pass it settings. drupal.stackexchange.com/questions/171686/…
    – Beebee
    Commented Nov 24, 2020 at 12:11
  • @Hudri is correct. A plugin should not depend from a controller class, nor a controller class should assume a block is available on the page it renders.
    – avpaderno
    Commented Nov 24, 2020 at 14:31
  • I already thought of creating a service for that but it seems to me sometimes that this is a little bit of overengineering. This is a very specific use case in my code. At the moment no other code depends on that "not so easy logic".It would be simpler to access the method on the controller already implementing it from within the block plugin to follow DRY and then refactor later in case this logic will be needed by some other code as well. A service for a logic just needed in two places deeply depending to each others seems too much for me. Commented Nov 25, 2020 at 6:13

1 Answer 1

1

You find the controller class in a request attribute:

$controller = \Drupal::request()->attributes->get('_controller');

You need to instantiate the controller and run the code a second time. For not-so-easy logic it might be a better idea to refactor the code to a service which then caches the result for the second run, as @Hudri commented.

Or take a different approach. Place a custom block with a static placeholder on the page and replace it by attaching bubbleable metadata to the controller output. See Add an attribute to $variables from a Controller

Instead of a render array you can also replace the placeholder in a lazy-builder callback. This depends on the structure of the data in controller and block and how dynamic this is. At the end this is all about caching performance.

1
  • Thank you.... I was hoping that the instantiated controller is stored somewhere. The method you describe additonally delivers the controller including the method as a string as defined in the route definition, e.g "\Drupal\my_module\Controller\MyConntroller::build". So it seems that my idea is not so good and I will use a service that. Commented Nov 25, 2020 at 13:07

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.