Controller Class

Standard Controller

<?php

/**
 * @file
 * Contains \Drupal\my_module\Controller\MyController.
 */

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;

class MyController extends ControllerBase {

  /**
   *  Called to generate the output used to display your dynamic page.
   *  Must return a valid render array
   */
  public function myMethod() {

    return array(
      '#markup' => "<p>Hello World</p>",
      '#attached' => array(
        'library' => array('my_module/my_controller'),
      ),
      '#cache' => array(
        'max-age' => 0,
      ),
    );

  }

  /**
   *  Same concept, but accepts a parameter provided by the route (see the
   *  sample my_module.routing.yml file)
   */
  public function myOtherMethod($action) {

    return array(
      '#markup' => "<p>Hello World.  My action is '" . $action . "'</p>",
      '#attached' => array(
        'library' => array('my_module/my_controller'),
      ),
      '#cache' => array(
        'max-age' => 0,
      ),
    );

  }


}

Controller with Dependency Injections

<?php

/**
 * @file
 * Contains \Drupal\my_module\Controller\MyController.
 */

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\user\PermissionHandlerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;

class MyController extends ControllerBase {

  protected $route_provider;
  protected $permissionHandler;
  protected $moduleHandler;
  protected $entityTypeManager;

  /**
   * Constructs a new controller.
   */
  public function __construct(RouteProviderInterface $route_provider, PermissionHandlerInterface $permission_handler, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager) {
    $this->routeProvider = $route_provider;
    $this->permissionHandler = $permission_handler;
    $this->moduleHandler = $module_handler;
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('router.route_provider')
      $container->get('user.permissions'),
      $container->get('module_handler'),
      $container->get('entity_type.manager')
    );
  }

  /**
   *  Called to generate the output used to display your dynamic page.
   *  Must return a valid render array
   */
  public function myMethod() {

    return array(
      '#markup' => "<p>Hello World</p>",
      '#attached' => array(
        'library' => array('my_module/my_controller'),
      ),
      '#cache' => array(
        'max-age' => 0,
      ),
    );

  }

}

Notes:

  • The filename must match the classname (e.g. "MyController.php" for the example above) and be placed in "src/Controller/" relative to your module's root directory.

  • Anything that starts with "my_" or "My_" should be adjusted to fit your module.  In particular, anything, any instance of "my_module" should be replaced with the machine name of your module.

  • Unlike with plugins, a controller doesn't have one pre-defined method for output generation.  Instead, the method to be used is defined in the route in "my_module.routing.yml".  In fact, a single controller can provide output for multiple routes via multiple methods, and its also possible to configure a route so that the last part of the URL gets passed to the method as a parameter (see myOtherMethod above).  Thus, myMethod above is just an example, and for it to be called, there would have to be a route defined that points to this controller class and specifies myMethod as the controlling method for that route.

  • The #markup example in the sample render array is valid, but it is preferred that you use actual render objects whenever possible.  See XYZ for a list of possible render objects.  You can also create your own render objects by adding your own TWIG templates to your module