32

In Drupal 7, I could change the page title with drupal_set_title(t('New page title')). When I try it in Drupal 8, I get a There is no such function error.

How can I change the page title?

11 Answers 11

39

As reported in drupal_set_title() and drupal_get_title() were removed that function is deprecated in Drupal 8.

For a dynamic title set from a controller, the code the change record suggests is the following one.

mymodule.test:
  path: '/mymodule/test'
  defaults:
    _controller: '\Drupal\mymodule\Controller\Test::getContent'
    _title_callback: '\Drupal\mymodule\Controller\Test::getTitle'

The controller code is the following one.

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;
  }

}

Alternatively, as the same change record suggests, you could use the #title property in a render array. This should be generally avoided, since the title for the page when fully rendered could be different from the title in other contexts (like in the breadcrumbs).

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;
   }

}
1
  • 1
    Why do you have to append the system.site->name? That is appended as part of the title that goes into html head if you provide a title string without that.
    – anoopjohn
    Nov 3 '19 at 1:10
8

drupal_set_title() in Drupal 8

$request = \Drupal::request();
if ($route = $request->attributes->get(\Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT)) {
  $route->setDefault('_title', 'New Title');
}

drupal_get_title() in Drupal 8

$request = \Drupal::request();
if ($route = $request->attributes->get(\Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT)) {
  $title = \Drupal::service('title_resolver')->getTitle($request, $route);
}
3
  • 1
    GET title works fine maybe everywhere. I wonder where to SET the title, cause in preprocess page it doesn't seem to work.
    – leymannx
    Mar 30 '17 at 9:35
  • Thanks @rpayanm! The above is what I need - to change title in my controller action without touching markup and w/o using getTitle(). Here is a more short version: $route = \Drupal::routeMatch()->getRouteObject(); $route->setDefault('_title', 'New Title'); Nov 19 at 14:59
  • Here is also cross-reference to the CR with different examples: drupal.org/node/2067859 Nov 19 at 15:02
6

Change the title tag in the head of your HTML document.

function mymodule_preprocess_html(&$variables) {

  $variables['head_title']['title'] = $something;
}

Change the title that appears in the page content.

function mymodule_preprocess_block(&$variables) {

  if ('page_title_block' == $variables['plugin_id']) {
    $variables['content']['#title'] = $something;
  }
}
5

That function was removed from Drupal 8.
Change record: drupal_set_title() and drupal_get_title() were removed.

You could now set the title when defining the routes in modulename.routing.yml. Example of how it could be done, is shown the change record link above.

4

I've found another way, which may be simpler if you don't have a controller and want to modify the title throughout your website. You can use it to modify the title based on the current node.

First, remove the tag in your html.html.twig Then, hook hook_page_attachments_alter

function mytemplate_page_attachments_alter(array &$page) {
    $page['#attached']['html_head'][] = [
        [
          '#tag' => 'title',
          '#value' => "My title"
        ],
        'title'
    ];
}

You can get the current node of taxonomy term with

$node = \Drupal::routeMatch()->getParameter('node');
$term = \Drupal::routeMatch()->getParameter('taxonomy_term')
4

I found in D8 that if you're wanting to alter the title for an entity view, you can use hook_ENTITY_TYPE_view_alter(). For example, here's how you could change the view of a user entity with a field on the user "field_display_name", rather than the user ID as the title:

/**
* Implements hook_ENTITY_TYPE_view_alter().
*/
function mymodule_user_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
  $build['#title'] = $entity->get('field_display_name')->getString();
}
1
  • Good and clean approach. Works fine in D8/ Feb 11 '19 at 22:26
2

Take a look at Automatic Entity Label, a very well crafted contributed module for setting node titles and the like.

(Note that 'page title' is a more colloquial way of saying 'entity label', where 'page' is a content entity and 'label' encompasses the title and the equivalent for other entities e.g. comment subjects, taxonomy term names.)

While op appears to be asking for guidance on writing custom code, it's not clear from available details that custom code is the best recommendation. For readers without a very specific reason for duplicating a feature available from contributed code, the Drupal community strongly advises (and site owners strongly benefit from) adopting an existing module.

2

drupal_set_title() and drupal_get_title() both are removed from drupal 8 but the best part is this there is a separate block for page_title. User can hide or add this block on any page/region.

There are 2 solutions for this.

  1. Disable title_block on particular page and add new custom block with some markup for title. Now place this block just after the title_block in drupal block section.
  2. By using hook_preprocess_block() function in your custom_theme.theme file.
    Here is the code example:

    function custom_themename_preprocess_block(&$variables) {
      if ('page_title_block' == $variables['plugin_id']) {
        $request = \Drupal::request();
        $path = $request->getRequestUri(); // get current path
        if(strpos($path, 'user')) { //check current path is user profile page
          $variables['content']['#title'] = 'My Profile';
        }
      }
    }
    

    In my case I have used above 2nd method, which will work only for user profile page.

0
1

I struggled with this and tried all of the solutions above. The solution that finally worked was:

function mymodule_preprocess_html(&$variables) {
  $variables['head_title']['title'] = $something;
}

but only after I updated my custom module weight:

drush php:eval "module_set_weight('mymodule', 10);"
1

Getting the page title works fine as written in @rpayanm's answer. But setting it turned out to be quite complicated. Finally found out that hook_preprocess_HOOK() could simply be used to preprocess the page title quite easily.

/**
 * Implements hook_preprocess_HOOK().
 */
function MYMODULE_preprocess_page_title(&$variables) {

  if ($MYLOGIC === TRUE) {

    $variables['title'] = 'New Title';
  }
}

And as already mentioned in other answers here you might additionally use hook_preprocess_html() to set the HTML head title tag accordingly.

0

i have changed the page_title block for user/uid to a different custom account field name like this :

function hook_preprocess_block(&$variables) {  
  $path = \Drupal::request()->getpathInfo();
  $arg = explode('/', $path);
  if (isset($arg[2]) && $arg[2] == 'user' && isset($arg[3])) {
    if (isset($variables['elements']['content']['#type']) && $variables['elements']['content']['#type'] == 'page_title') {
      $account = \Drupal\user\Entity\User::load($arg[3]);
      if(isset($account) && isset($account->field_mycustomfield->value)){
        $variables['content']['#title']['#markup']=$account->field_mycustomfield->value;
      }
    }
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.