0

I have a drupal 10 website. I have to set a cookie for the first time the user visits the site, a cookie with a lifetime of 1 year. When the user first visits the website, the cookie is not set, a welcome message block appears, the cookie is then set, then the next time the user visits the site, the cookie is already set so the message block doesn't appear. I am calling my block in a region using {{elements.blockId}} So I know that I have to check if the cookie exists in the preprocess_region and based on its value, i check whether i should print the block or not.

However, I don't know where do I have to set the cookie? In some page_attachment function?

I have read this How do I set a cookie? And I thought I should use

use Symfony\Component\HttpFoundation\Cookie;

$cookie = new use Cookie('cookie_name', TRUE);
$response->headers->setCookie($cookie);
return $response;

But I don't have a controller? Where Can i add this code to return a response?

5
  • Cookies must be set in the context of a response from the backend or using Javascript on the frontend.
    – Kevin
    Jan 19 at 18:45
  • Thanks @Kevin but if I set it in javascript, how would i detect it in twig in the region template? If i use JS, I ll be forced to render the block in all cases in the region template and then hide it using js .
    – Mira
    Jan 19 at 19:54
  • Also, FWIW there is probably a contributed module that does this.
    – mona lisa
    Jan 20 at 12:04
  • Notice that new use Cookie() is not correct. use needs to be removed.
    – apaderno
    Jan 20 at 16:34
  • Noted, Thanks !
    – Mira
    Jan 20 at 20:13

1 Answer 1

0

Since you want to show a message when the cookie has not been set, you could implement hook_page_top().

/**
 * Implements hook_page_top().
 */
function mymodule_page_top(array &$page_top) {
  $messenger = \Drupal::messenger();
  $request = \Drupal::request();

  if (!$request->cookies->get('cookie_name', FALSE) {
    // Show a message using $messenger.
    $messenger->addStatus('Your message');

    // Add the cookie using JavaScript.
    $page_top['#attached']['html_head'][] = [
      ['#tag' => 'script',
        '#value' => 'document.cookie = "cookie_name=1; path=/; expires=' . date(DATE_COOKIE, strtotime("+1 year")) . '"',
      ],
      'mymodule_add_cookie_js',
    ];
  }
}

system_page_top() is an example of hook_page_top() implementation that uses the messenger to show messages.
big_pipe_page_attachments() is an example of hook implementation that sets a cookie using JavaScript (using #attached).

8
  • What a great answer !! Thanks! However I have a block, contained within a region, that includes my message with a photo.Can i do the same but instead of my_module_page_top, i do preprocess for that region? Or i can't attach a js to a region?
    – Mira
    Jan 21 at 16:41
  • Plus can i do it in theme not in module so that js will be attached on front only?
    – Mira
    Jan 21 at 16:43
  • And lastly, does this cookie get cached? Because once i used setcookie php function and the cookie was cached a lot
    – Mira
    Jan 21 at 16:45
  • A preprocess hook is too late for that. That is why the BigPipe module does not use any preprocess hook for a similar task. As for caching, if the code shown in the answer does not avoid the cookie is cached, you could verify what happens when $page_top['#cache']['contexts'][] = 'cookies:cookie_name'; (which should avoid the content is cached when the cookie is changed) or $page_top['#cache']['max-age'] = 0; (which should avoid the page is cached) is added.
    – apaderno
    Jan 21 at 18:16
  • Thank you so much ! Super detailed answer !
    – Mira
    Jan 21 at 20:35

Your Answer

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

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