Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Controllers

A controller is a class whose methods build the response to a request. The route from the previous lesson names the class and the method, and the controller decides what to show on the page.

Where a controller lives

Module classes are kept in the src folder. Controllers go to src/Controller by convention. Create the folders and the file by hand:

mkdir -p web/modules/custom/blog/src/Controller

The first controller

// web/modules/custom/blog/src/Controller/BlogController.php
namespace Drupal\blog\Controller;
 
use Drupal\Core\Controller\ControllerBase;
 
class BlogController extends ControllerBase
{
    public function list(): array
    {
        return [
            '#markup' => 'The list of articles will be here.',
        ];
    }
}

In the real file the first line is <?php. Run drush cr and open /blog: a site page appears with the title Blog and the text from the controller. Drupal added the header, menu and footer itself.

Naming rules

Drupal finds the class by its namespace, so the file path and the class name must match.

FileClass
blog/src/Controller/BlogController.phpDrupal\blog\Controller\BlogController
blog/src/Form/SubscribeForm.phpDrupal\blog\Form\SubscribeForm

The beginning Drupal\blog corresponds to the blog/src folder; after that the namespace repeats the nested folders.

What a method returns

A method returns not an HTML string but a render array — a description of what to show. The #markup key means "output this markup". Drupal builds the page with the theme around it. Render arrays are covered in detail in the next chapter.

A second method

For the blog.about route from the previous lesson, add one more method to the same class:

// web/modules/custom/blog/src/Controller/BlogController.php
public function about(): array
{
    return [
        '#markup' => $this->t('A blog about Drupal development.'),
    ];
}

The /blog/about page shows this text. The $this->t() method from ControllerBase makes the string translatable — translation has its own lesson.

Other kinds of response

If you need not a site page but a bare response, the method returns a response object:

// web/modules/custom/blog/src/Controller/BlogController.php
use Symfony\Component\HttpFoundation\JsonResponse;
 
public function status(): JsonResponse
{
    return new JsonResponse(['status' => 'ok', 'articles' => 3]);
}

The browser gets JSON without a header or a menu. To redirect to another route, ControllerBase has the method $this->redirect('blog.list').

What ControllerBase gives you

MethodWhat it returns
$this->t('Text')A translatable string
$this->currentUser()The current user
$this->entityTypeManager()Access to nodes and other entities
$this->config('blog.settings')Module settings
$this->messenger()Messages to the visitor
$this->redirect('blog.list')A redirect to a route

Common mistake

A message saying the controller class does not exist almost always means mismatched names. Check three things: the file is exactly in src/Controller, the file name equals the class name including case, and the namespace is Drupal\blog\Controller. In blog.routing.yml the class path starts with a backslash and the method is separated by two colons.

Thanks for reading!

Donate to the site — we work hard for you.