11

I need to save a cookie for anonymous users in Drupal 8 when users visit the site for the first time, which will be used to display a message.

I can successfully save one using setcookie("FirstTimer", 1, strtotime('+1 year')); but I am sure Drupal 8 should have some alternatives.

I can also use the following code.

$user_is_first_timer = !isset($_COOKIE["Drupal_visitor_FirstTimer"]); 

When I open it in Google Chrome, this works, but when I open it in incognito or in Firefox, there is no message. Somehow cached pages are being served.

The code is used in an implementation of hook_page_attachments().

2 Answers 2

14

With Drupal 7, Drupal 8, and Drupal 9 you could use user_cookie_save() to store a cookie.

function user_cookie_save(array $values) { foreach ($values as $field => $value) { // Set cookie for 365 days. setrawcookie('Drupal.visitor.' . $field, rawurlencode($value), REQUEST_TIME + 31536000, '/'); } } 

The first parameter is an array, whose keys are the names of the cookies to set and its values are the cookie values.
user_cookie_save() doesn't allow to set when a cookie expires; cookies created with this function expires after 365 days.

The only method that in Drupal 8 calls user_cookie_save() is SystemController::compactPage().

public function compactPage($mode) { user_cookie_save(['admin_compact_mode' => $mode == 'on']); return $this->redirect('<front>'); } 

Unfortunately, there isn't an equivalent function to read a cookie. In Drupal 8 and Drupal 9, to read the cookie saved from SystemController::compactPage() it's used system_admin_compact_mode().

function system_admin_compact_mode() { // PHP converts dots into underscores in cookie names to avoid problems with // its parser, so we use a converted cookie name. return \Drupal::request()->cookies->get('Drupal_visitor_admin_compact_mode', \Drupal::config('system.site')->get('admin_compact_mode')); } 

In alternative, in Drupal 8 and Drupal 9, you could store cookies using code similar to the one used by BigPipeController::setNoJsCookie() (implemented since Drupal 8.1.x).

if ($request->cookies->has(BigPipeStrategy::NOJS_COOKIE) || !$request->hasSession()) { throw new AccessDeniedHttpException(); } if (!$request->query->has('destination')) { throw new HttpException(400, 'The original location is missing.'); } $response = new LocalRedirectResponse($request->query->get('destination')); // Set cookie without httpOnly, so that JavaScript can delete it. $response->headers->setCookie(new Cookie(BigPipeStrategy::NOJS_COOKIE, TRUE, 0, '/', NULL, FALSE, FALSE, FALSE, NULL)); $response->addCacheableDependency((new CacheableMetadata()) ->addCacheContexts([ 'cookies:' . BigPipeStrategy::NOJS_COOKIE, 'session.exists', ])); return $response; 

This code used the $response object from Symfony, instead of using a PHP function.
It's also more "symmetric," as the same object allows to read and write cookies.

Using $response->headers->setCookie() gives more control over the cookie parameters (the parameters Cookie::__construct() accepts).

0
9

Drupal 8 cookies can be set using ResponseHeaderBag from the Symfony\Component\HttpFoundation\Response object.

Set new cookie value

use Symfony\Component\HttpFoundation\Cookie; $cookie = new Cookie('cookie_name', 'cookie_value'); $response->headers->setCookie($cookie); return $response; 

Get cookies value

$request->cookies->get('cookie_name'); 
1
  • use must be removed from new use Cookie('cookie_name', TRUE). Commented Jan 20, 2024 at 16:32

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.