Module Development

Controllers for Drupal 8, 9, and 10

When Drupal receives an incoming request the HTTP Kernel identifies the appropriate route for the requested path. The routing system then matches this route with a controller that has been registered to handle responses for these types of requests. Sections of code responsible for generating the response to these requests are called Controllers.

Example tasks

  • Write the code in a custom module that responds to particular incoming requests
  • Understand how to identify the controllers responsible for responding to a given url, path and route.


Drupal's system of mapping request routes to controllers is quite well established. Since it's based on Symfony components it is unlikely to change dramatically in the foreseeable future.

Drupalize.Me resources

This tutorial covers how controllers work in the Symfony framework. Because Drupal is built on top of Symfony components, controllers in Drupal are very similar.

More information

Let's create our first page in our Symfony 4 app and learn about routes and controllers in the process.

More information

In this tutorial, we'll create a new module and create a route and controller for it. Remember hook_menu? Well, hook_menu is out and routes and controllers are in! If the YAML files in this lesson piqued your interest, check out our introduction to YAML tutorial to learn more.

Note: See Create an Info File for a Module for up-to-date instructions on info file requirements, which have changed since this video was recorded.

Create an Info File for a Module
An Introduction to YAML — Drupalize.Me
PHP Namespaces in 120 seconds
Clear Drupal's Cache

More information

In this tutorial, we'll continue to look under the hood of Drupal 8, this time using a tool bundled with Devel called Webprofiler. You'll learn how to use the web debug toolbar and the profiler. You'll also learn how to reverse engineer a page to find out the names of the controllers responsible for output on that page.

Note: Webprofiler is now a separate project from Devel but still has it as a dependency.

Note: In order to get the Webprofiler timeline view working you need to add some configuration to your settings.php file. See the file included with the Webprofiler module for more information on how to do this.

Webprofiler project on

Controllers and Form API

More information

Each form is defined by a controller, a class that implements the \Drupal\Core\Form\FormInterface. Form controllers declare the unique ID of the form, the $form array that describes the content of the form, how to validate the form, and what to do with the data collected.

In this tutorial we'll:

  • Define a new form controller class
  • Implement the required methods to describe a form
  • Add a route that can be used to access our form

By the end of this tutorial you should be able to define a form that adheres to the FormInterface requirements and know where to find more information about how to further customize your form controller.

More information

When your module defines the form and the form controller, you can add your validation logic as part of the form controller. This is done via the implementation of a validateForm() method. The FormBuilder service will automatically invoke this method at the appropriate time during the process of submitting a form. While the validateForm() method is required by \Drupal\Core\Form\FormInterface, an empty method will fulfill that requirement. It's up to you to provide appropriate validation code inside the method.

In this tutorial we'll:

  • Use the validateForm() method of a form controller to verify user input
  • Demonstrate how to raise errors on a form element when it doesn't pass validation

By the end of this tutorial you should know how to validate your custom forms.

More information

When you create a custom form for Drupal and your module defines the form controller, the best way to handle processing of submitted data is via the submitForm() method of your controller. This method is called automatically by the Form API during the process of handling a user-submitted form. It can be used to save incoming data to the database, trigger a workflow based on user input, and instruct the Form API where to send the user after form processing has completed.

In this tutorial we'll:

  • Demonstrate how to add a submitForm() method to a form controller class
  • Access the value(s) of form input elements via the $form_state object
  • Set a redirect after performing processing in a form submission handler

By the end of this tutorial you should know how to access the values of a submitted form, and how to write custom processing code inside of the submitForm() method of a form controller.

More information

Eventually you'll want to do something with the information your form collects beyond just printing it to the screen. It's generally considered a best practice to keep business logic out of your form controller so that it can be reused. In order to accomplish that you'll generally define your business logic in a service, and then call out to that service from your form controller. Or, you can make use of one of the existing services provided by Drupal core to save data.

In this tutorial we'll:

  • Use dependency injection to inject a service into a form controller
  • Make use of a service injected into a form controller from within the buildForm() and submitForm() methods

By the end of this tutorial you'll understand how to inject one or more services into your form controller and then make use of them.

Related topics


Drupal 8, 9, and 10
More information

In Drupal, routes help map the URL of an incoming request to the code responsible for generating the content that is rendered in response.


Drupal 8, 9, and 10
More information

Symfony is a set of reusable PHP components, and a framework for building PHP applications. Drupal makes use of various Symfony components.


Not sure where to start? Our guides provide useful learning tracks for all skill levels.

Navigate guides

External resources

  • Adding a basic controller (
    • This tutorial covers creating a very basic controller.
  • Examples for Developers project's page_example module (
    • The Examples project contains many sub-modules that demonstrate various Drupal sub-systems through well-documented code. To learn more about how routing and controllers work, take a look at the page_example module here.