10

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().

10

With Drupal 7, Drupal 8, and Drupal 9 you can 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 function parameter is an array. Its keys are the names of the cookies to set; its values are the values to set for those cookies.
user_cookie_save() doesn't allow to set when a cookie expires; cookies created with this function expires after 365 days.

There is just a method in Drupal 8 core class that uses user_cookie_save(): 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. Drupal 8 and Drupal 9, to read the cookie saved from SystemController::compactPage() uses 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'));
}

The other function/method I found that stores cookies in Drupal 8 and Drupal 9 is BigPipeController::setNoJsCookie() (implemented since Drupal 8.1.x) which uses the following code.

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;

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

0
5

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 use Cookie('cookie_name', TRUE);
$response->headers->setCookie($cookie);
return $response;

Get cookies value

$request->cookies->get('cookie_name');

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.