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