21

In Drupal 7 we can simply check if the current user is logged-in in a theme by checking $GLOBAL['user']->uid or using user_is_logged_in().

How can I check if a user is logged-in in a page template, in Drupal 8?

A solution is to manually check in hook_preprocess_page(), but since this is very popular, I think Drupal provides something by default for the Twig theme engine.

6 Answers 6

37

If you just need to verify the current user is logged-in, you can use $variables['logged_in'], which is generally available in all the template files.

For example, the mark.html.twig file uses the following code, although the only documented variable is status.

{% if logged_in %}
  {% if status is constant('MARK_NEW') %}
    <span class="marker">{{ 'New'|t }}</span>
  {% elseif status is constant('MARK_UPDATED') %}
    <span class="marker">{{ 'Updated'|t }}</span>
  {% endif %}
{% endif %}

The variable is explicitly documented in other template files, such as html.html.twig, page.html.twig, and node.html.twig.

The variable is available in all the template files, since it is initialized in _template_preprocess_default_variables() that invokes user_template_preprocess_default_variables_alter() (an implementation of hook_template_preprocess_default_variables_alter()), which contains the following code.

  $user = \Drupal::currentUser();

  $variables['user'] = clone $user;
  // Remove password and session IDs, since themes should not need nor see them.
  unset($variables['user']->pass, $variables['user']->sid, $variables['user']->ssid);

  $variables['is_admin'] = $user->hasPermission('access administration pages');
  $variables['logged_in'] = $user->isAuthenticated();

_template_preprocess_default_variables() is called by template_preprocess(), which is the function called for theme hooks implemented as templates; this guarantees the variable is available in all the template files.

Keep in mind that macros don't have access to the current template variables, so trying to access logged_in in the code of a macro would not have any effect.
Between the template files used from Drupal core modules, the ones using a macro are:

  • menu.html.twig

      {% macro menu_links(items, attributes, menu_level) %}
        {% import _self as menus %}
        {% if items %}
          {% if menu_level == 0 %}
            <ul{{ attributes }}>
          {% else %}
            <ul>
          {% endif %}
          {% for item in items %}
            <li{{ item.attributes }}>
              {{ link(item.title, item.url) }}
              {% if item.below %}
                {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
              {% endif %}
            </li>
          {% endfor %}
          </ul>
        {% endif %}
      {% endmacro %}
    
  • book-tree.html.twig

      {% macro book_links(items, attributes, menu_level) %}
        {% import _self as book_tree %}
        {% if items %}
          {% if menu_level == 0 %}
            <ul{{ attributes }}>
          {% else %}
            <ul>
          {% endif %}
          {% for item in items %}
            <li{{ item.attributes }}>
              {{ link(item.title, item.url) }}
              {% if item.below %}
                {{ book_tree.book_links(item.below, attributes, menu_level + 1) }}
              {% endif %}
            </li>
          {% endfor %}
          </ul>
        {% endif %}
      {% endmacro %}
    
  • menu--toolbar.html.twig

      {% macro menu_links(items, attributes, menu_level) %}
        {% import _self as menus %}
        {% if items %}
          {% if menu_level == 0 %}
            <ul{{ attributes.addClass('toolbar-menu') }}>
          {% else %}
            <ul class="toolbar-menu">
          {% endif %}
          {% for item in items %}
            {%
              set classes = [
                'menu-item',
                item.is_expanded ? 'menu-item--expanded',
                item.is_collapsed ? 'menu-item--collapsed',
                item.in_active_trail ? 'menu-item--active-trail',
              ]
            %}
            <li{{ item.attributes.addClass(classes) }}>
              {{ link(item.title, item.url) }}
              {% if item.below %}
                {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
              {% endif %}
            </li>
          {% endfor %}
          </ul>
        {% endif %}
      {% endmacro %}
    

For example, changing the last macro with the following code would not have the expected result.

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('toolbar-menu') }}>
    {% else %}
      <ul class="toolbar-menu">
    {% endif %}
    {% for item in items %}
      {%
        set classes = [
          'menu-item',
          logged_in ? 'menu-item--logged-in-user',
          item.is_expanded ? 'menu-item--expanded',
          item.is_collapsed ? 'menu-item--collapsed',
          item.in_active_trail ? 'menu-item--active-trail',
        ]
      %}
      <li{{ item.attributes.addClass(classes) }}>
        {{ link(item.title, item.url) }}
        {% if item.below %}
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}
3
  • The variable is surely available in all the template files I am afraid you are wrong regarding this. If the template does not mention it in the comments, there must be a reason, right? Because I tried on menu.html.twig (which does not mention it in the comments) and did not work. While using Twig Extender it works.
    – No Sssweat
    Sep 16, 2016 at 9:00
  • _template_preprocess_default_variables() is called for every template Drupal outputs, so the variables it adds are present in all the template files. Documentation doesn't document all the default variables, as far as I can see.
    – apaderno
    Sep 16, 2016 at 9:05
  • 2
    @kiamlaluno whenever you have free time, try {% if logged_in %} on menu.html.twig and you'll see it doesn't work. Didn't work for me.
    – No Sssweat
    Sep 16, 2016 at 9:06
5

You can with the Twig Extender module. Quote from its project page:

Add a simple plugin system to add new twig extensions (Filter and Functions). Provides a new service provider for "twig.extensions" to add new plugins.

Function: is_user_logged_in

Check if user is logged in.

{% if user_is_logged_in() %}
Hello user
{% else %}
Please login
{% endif %}
3
  • only 57 use and beta :(. maybe thee better solution is ` $vars['is_login'] = !\Drupal::currentUser()->isAnonymous(); ` in preprocess_page ? what is your opinion?
    – Yuseferi
    Jul 13, 2016 at 13:22
  • 3
    There is no need of a module for that functionality, since Drupal core has already it. See my answer.
    – apaderno
    Jul 13, 2016 at 17:09
  • @kiamlaluno Yes, I agree with you, this requirement is very popular and I was sure drupal had provided something for it.
    – Yuseferi
    Jul 14, 2016 at 6:35
2

For everybody trying to use logged_in from menu.twig.html; you need to call it from outside the menus.menu_links() macro as the logged_in variable is out of scope within the macro.

1

You can check if the user is authenticated like so:

For example, I have created the following function in themename.theme.

# Function to get user logged info
function tropical_preprocess_page(&$variables){
  // if user is authenticated
  if($variables['user']->isAuthenticated()){
    # gets username
  $user_logged_in_name = $variables['user']->getDisplayName();
  # creates value to ouput in the DOM & capitalize first letter
  $variables['user_logged_in_name'] = ucfirst($user_logged_in_name);

  # gets user email
  $user_email = $variables['user']->getEmail();
  $variables['user_email'] = $user_email;

  // get user picture
  $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
  $variables['user_picture'] = $user->get('user_picture')->entity->url();

  // Check if user is logged in
  $user_logged = $variables['user']->isAuthenticated();
  $variables['user_logged'] = $user_logged;
  }
}

After that, you can create the logic within the Twig file like so:

<div class="user-logged-greeting">
  {% if user_logged %}
    <h2>Welcome back, {{ user_logged_in_name }}!</h2>
    <p>The email for this user is: <strong>{{ user_email }}<strong></p>
    <img src="{{ user_picture }}" width="50" height="50">
  {% endif %}
</div>

If the user is logged in, you will get the greeting message along with username, email & avatar picture. If user is not logged in, it won't show up anything.

Let me know if that helps and/or if I can edit this post for better understanding.

0

The issue isn't that the variable doesn't exist in the template file, but rather that it isn't available in the macro. You can fix this via passing it through:

{% macro menu_links(items, attributes, menu_level, logged_in) %}

Then if you have a signin menu item, something like:

{% if item.title == 'Sign In' %} {% if not logged_in %} Go to login {% endif %} {% endif %}

1
  • Unfortunately this doesn't work.
    – erier
    Jun 14, 2020 at 22:25
0

I moved my login-sensitive button "Login" outside the menu macro. So the twig variable logged_in which is not in scope inside the macro could be used again.

Before moving the login-sensitive button (which did not work):

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
<ul{{ attributes.addClass('menu') }}>
  {% else %}
  <ul class="menu">
    {% endif %}
    {% for item in items %}
...
    {% endfor %}

    {% if logged_in %}
    <li class="menu-item register">
      <a href="/user" data-drupal-link-system-path="<front>" class="btn btn-light">{{ 'My user account'|t }}</a>
    </li>
    {% else %}
    <li class="menu-item register">
      <a href="/user/login" data-drupal-link-system-path="<front>" class="btn btn-light">{{ 'Login'|t }}</a>
    </li>
    {% endif %}
  </ul>

  {% endif %}
  {% endmacro %}

After moving the login-sensitive button (works for me):

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
<ul{{ attributes.addClass('menu') }}>
  {% else %}
  <ul class="menu">
    {% endif %}
    {% for item in items %}
...
    {% endfor %}
  {% endif %}
{% endmacro %}

{% if logged_in %}
  <li class="menu-item register">
    <a href="/user" data-drupal-link-system-path="<front>" class="btn btn-light">{{ 'My user account'|t }}</a>
  </li>
{% else %}
  <li class="menu-item register">
    <a href="/user/login" data-drupal-link-system-path="<front>" class="btn btn-light">{{ 'Login'|t }}</a>
  </li>
{% endif %}
</ul>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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