Problem/Motivation

Drupal 7:

  $title = drupal_get_title();

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

Do I need to tell more how is this wrong?

Proposed resolution

$title = Foo:bar()

Remaining tasks

Come up with a name, implement it.

User interface changes

API changes

Comments

chx’s picture

Title: Add back a simple title getter » Add back a simple page title getter
dawehner’s picture

Using drupal_get_title() is not really a good approach in general, because it acts as it would get you the right one all the time.

The better way would be to use the page object once it does exists and get the title from there.

catch’s picture

Status: Active » Postponed (maintainer needs more info)

#2256669: [meta] Finalize module-facing API of getting the matched route name and a matched route argument for a request should improve getting the current route.

I don't think the second example in the issue summary actually works all the time, since we have the '#title' property used instead of calls to drupal_get_title() within page callbacks. Getting the title from the route is like manually invoking the title callback in 7.x - only covers half the possibilities. So the example code, while ugly, shouldn't be used anyway.

I think dawehner's right that the getter already exists: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Page%21Ht...

The question then becomes does everywhere have access to the HtmlPage object that might need it. This is 'needs more info' until that's documented.

#2218271: Theme preprocess functions have to futz with $page_object = $variables['page']['#page'] in weird ways is related since we're exposing the page object a bit too much there.

dawehner’s picture

The question then becomes does everywhere have access to the HtmlPage object that might need it. This is 'needs more info' until that's documented.

It basically comes down to the previous problem in D6/D7 that you might call drupal_get_title() to a point where some custom drupal_set_title() has not been called yet.

As far as I understand the problem most usecases actually deal with stuff on the page level, like some google analytics JS or really special theming. Panels could be another candidate for a usecase, but there you also work on the page level.

dawehner’s picture

The question then becomes does everywhere have access to the HtmlPage object that might need it. This is 'needs more info' until that's documented.

The time this object exists is during the kernel::view level. For example these events allow to pull the title to send it to some javascript.
what are other usecases?

benjy’s picture

Is there a new approach to this now HtmlPage and HtmlFragment are gone?

wim leers’s picture

Status: Postponed (maintainer needs more info) » Active

I don't think the second example in the issue summary actually works all the time, since we have the '#title' property used instead of calls to drupal_get_title() within page callbacks. Getting the title from the route is like manually invoking the title callback in 7.x - only covers half the possibilities. So the example code, while ugly, shouldn't be used anyway.

Indeed.

It basically comes down to the previous problem in D6/D7 that you might call drupal_get_title() to a point where some custom drupal_set_title() has not been called yet.

And that indeed was and is a problem.

Overall, the problem is that just using the usual title mechanism (routing system in D8, menu system in D7) only was able to account for static and "structured dynamic" titles. But we still have the need for "extremely dynamic" titles, and that's why in D7 and D8 alike, any code retrieving the page title (using drupal_get_title() in D7) must run very, very late, or it will not return the correct result. Specifically, the main content callback must have already been called and have had drupal_render() invoked.

Is there a new approach to this now HtmlPage and HtmlFragment are gone?

Good question. It's fundamentally still the same problem: any code wanting to get the page title must run extremely late.

Before we spend any more time on this, I think we should understand what the use cases are.

AFAIK the way D8 is designed, every route should have an associated title (let's call this "the routing title"). It is then possible for a #title property on the render array returned by the controller to override whatever the associated title would be (let's call this "the overriding title").
This implies that e.g. for breadcrumbs it is expected that we use "the routing title" rather than "the overriding title", otherwise we'd have to execute the controller associated with each breadcrumb… which would be insane.

If I look at the drupal_get_title() calls in D7 core, then I see 9 calls. Two are for test coverage. That leaves 7. One is for the page cache and is no longer needed. Leaves 6. One is for statistics.module, which is now done in JS, which makes more sense since it allows Drupal to serve from caches. Leaves 5. All remaining five occurrences are either hook_preprocess_page() implementations, where by design you can access the title, or hook_preprocess_html(), where the same applies.


I would personally argue that those last five are the only sane use cases for getting "the final title", and in D8 you get them there without having to call a function with a "global static" to know which is the final title. And if people agree with that, then we can close this issue.

Unless somebody can think of a valid use case for something like drupal_get_title(), keeping in mind that it is impossible to guarantee that you can call such a function at any time during the page generation time; we can only promise it works very, very late in the pipeline. The reason being that we want main content controllers be able to dynamically generate a title, and as a direct consequence, we can only get "the final title" very, very late. Especially Views needs this. If you want to work on removing that need, see #2359901: Discourage $main_content['#title'] in favor of route titles and title callbacks, where I attempted that, but got stuck.

dawehner’s picture

Well there is a world outside of core, obviously.

Module would probably never use hook_preprocess_page to get the title, but isn't there a place where we have set the #title on the main content render array?
Currently there is no point in which #titlepoints certainly to the proper title, but could we not provide a point to do that?

wim leers’s picture

Well there is a world outside of core, obviously.

Of course.

Currently there is no point in which

#title

points certainly to the proper title, but could we not provide a point to do that?

I don't see how, as long as we allow $page['#title']. Drupal 8 aims to return as thin as possible render arrays (postponing as much work as possible to #pre_render callbacks, hence work we don't need to do on render cache hits). In many (most?) cases, the main content's #title will only be set by a #pre_render callback… which means the title will only be available after rendering the main content, which happens very, very late in the game: after MainContentViewSubscriber calls HtmlRenderer. This happens before blocks are built. So we could make something like drupal_get_title() (with a static variable in its implementation) work to get the current page's title for blocks. But it won't be available while rendering the main content.

What's a good use case for using the current page's title in a block?

dawehner’s picture

What's a good use case for using the current page's title in a block?

One really good usecase is the usecase of panels everywhere, which takes over the renderong of the full page.html.twig basically,
so you need to be able to get the title into that somehow.

One thing what panels did in d6/d7 was to be able to render things later, so render things after
all of the others ones was rendered. I think the corresponding functionality in D8 would be a #post_render callback
which fills in the title later. Do you think something like that on the level of the the page variant is a good idea?

catch’s picture

Priority: Critical » Normal

Unless this is actually blocking panels everywhere, it looks like just an API addition to me and not critical. If someone can come up with a more common use case for getting the page title that's not met by the core API and is blocking contrib module/theme ports, we could reconsider.

wim leers’s picture

StatusFileSize
new1.11 KB

One thing what panels did in d6/d7 was to be able to render things later, so render things after
all of the others ones was rendered. I think the corresponding functionality in D8 would be a #post_render callback
which fills in the title later. Do you think something like that on the level of the the page variant is a good idea?

Yes! And this is actually almost completely supported by HtmlRenderer + page display variants already :)

See HtmlRenderer::prepare(). You'll see in there that we:

  1. first render the $main_content
  2. then use $main_content['#title'] as the title, if it is set
  3. call the selected page display variant's build() method to generate $page
  4. return the generated $page plus the title; we use $main_content['#title'] if it's set, and otherwise we use TitleResolver (the returned title is used for <title> in the HTML <head>)

This is theoretically enough already, because it means PanelsPageVariant would:

  1. receive the title via $main_content['#title'], if the main content has a dynamic title
  2. if that is not set, then PanelsPageVariant could call TitleResolver itself

… but then in the second case, HtmlRenderer::prepare() would retrieve the title again.

So in order to resolve this, I think all that we want to do is change

    // Determine the title: use the title provided by the main content if any,
    // otherwise get it from the routing information.
    $title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject());

to:

    $title = isset($page['#title']) ? $page['#title'] : isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject());

I.e. first try $page (in case the page display variant calls TitleResolver or has its own logic to determine the title), then use the main content's title, if any, and finally, use the TitleResolver as the fallback.

Thoughts? :)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

I'm wondering whether we could add a method to TitleResolver which is like: getTitleForCurrentRequest(), it would at least get rid of most of the hassle?

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

andypost’s picture

Version: 8.8.x-dev » 9.1.x-dev

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

Status: Active » Needs review

There's WIP patch

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new100 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

mrinalini9’s picture

Status: Needs work » Needs review
StatusFileSize
new1.1 KB

Rerolled patch #12 for 10.1.x, please review it.

Thanks & Regards,
Mrinalini

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs issue summary update

This issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.

This needs an issue summary update as the title and description talk about adding a getting method. But the patches are updating comments.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.