Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

drupal_set_title()

Titles on routes now can be set on various ways, depending on your usecase.
Previously just drupal_set_title() was called in whatever place. The following usecases exists:

  1. Static title:
    For static titles you set a '_title' on the routing definition:
    block.admin_add:
      path: '/admin/structure/block/add/{plugin_id}/{theme}'
      defaults:
        _content: '\Drupal\block\Controller\BlockAddController::blockAddConfigureForm'
        _title: 'Configure block'
      requirements:
        _permission: 'administer blocks'
  2. Dynamic title:
    If you write a controller and you need a dynamic title, for example depending on the site configuration, use _title_callback in the route defaults.
    mymodule.test:
      path: '/mymodule/test'
      defaults:
        _content: '\Drupal\mymodule\Controller\Test::getContent'
        _title_callback: '\Drupal\mymodule\Controller\Test::getTitle'

    <?php
    class Test {
     
    /**
       * Returns a page title.
       */
     
    public function getTitle() {
        return 
    'Foo: ' . \Drupal::config()->get('system.site')->get('name');
      }
     
    /**
       * Returns a page render array.
       */
     
    public function getContent() {
       
    $build = array();
       
    $build['#markup'] = 'Hello Drupal';
        return
    $build;
      }
    }
    ?>
  3. Final title override:

    If you write a controller and you need to override the title from the route, you can return #title in the render array. This should generally to be avoided, since the title for the page when fully rendered could be different from the title in other contexts (like in the breadcrumb).

    <?php
    class Test {
     
    /**
       * Renders a page with a title.
       *
       * @return array
       *   A render array as expected by drupal_render()
       */
     
    public function getContentWithTitle() {
       
    $build = array();
       
    $build['#markup'] = 'Hello Drupal';
       
    $build['#title'] = 'Foo: ' . Drupal::config()->get('system.site')->get('name');
        return
    $build;
      }
    }
    ?>

updated to include #2076085: Resolve the need for a 'title callback' using the route

Output flag of drupal_set_title #

The output validation in drupal 8 is opposite to Drupal 7. We have to explicitly specify PASS_THROUGH and CHECK_PLAIN is by default in Drupal 7, whereas in Drupal 8 PASS_THROUGH is by default and CHECK_PLAIN equivalent String::checkPlain need to be added where it is necessary. Here is an example:

Drupal 7:

<?php
drupal_set_title
(t('Add new shortcut'));
?>

Drupal 8:

<?php
$form
['#title'] = String::checkPlain($this->t('Add new shortcut'));
?>

Drupal 7:

<?php
drupal_set_title
(t("%name block", array('%name' => $info[$block->delta]['info'])), PASS_THROUGH);
?>

Drupal 8

<?php
$form
['#title'] = $this->t("'%name' block", array('%name' => $info[$block->delta]['info']));
?>

drupal_get_title()

Titles on routes now can be set on various ways, depending on your use case, this includes setting a static or dynamic title in the routing, or setting the title in the render array. drupal_set_title() no longer exists.

Consequently, drupal_get_title() has been removed, and in its place you should call the title_resolver service.

Drupal 7:

<?php
  $title
= drupal_get_title();
?>

Drupal 8:

<?php
  $request
= \Drupal::request();
  if (
$route = $request->attributes->get(\Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT)) {
   
$title = \Drupal::service('title_resolver')->getTitle($request, $route);
  }
?>
Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done