You will want to delete your cookie before any content is written to the page (before headers are sent).
To set the cookie, include the path, domain, and I also recommend setting the last 2 parameters to true ($secure
and $httponly
). You will also need to supply the same parameters to setcookie()
when deleting, aside from the $expiry
(which should be negative) and the $value
(which should be empty '').
If you are passing json through the cookie, it seems like you need to base64_encode
it as well, or it won't properly decode.
All of this should be done in a class so you can access the value of the cookie later on in your code. The class can be added to a plugin or functions.php.
Here is an example where we use a cookie to store an action response to then display it to the user after we redirect them:
class my_custom_class {
const MY_COOKIE_NAME_JSON = 'my_cookie_name_json';
const COOKIE_LIFETIME = 3600;
private $cookie_value;
function __construct() {
// ensure you are deleting cookie before headers are sent
add_action('init', [$this, 'process_cookie_json'], 10);
// uses bootstrap alert to format return message
add_filter('the_content', [$this, 'filter_the_content_in_the_main_loop'], 1);
}
static function some_action_that_sets_the_cookie($message, $response_type = 'success') {
$responses = [];
if (isset($_COOKIE[self::MY_COOKIE_NAME_JSON]))
$responses = json_decode(base64_decode($_COOKIE[self::MY_COOKIE_NAME_JSON]));
$responses[$response_type][] = $message;
self::set_cookie_json($responses);
}
static function set_cookie_json(array $cookie_value) {
setcookie(self::MY_COOKIE_NAME_JSON, base64_encode(json_encode($cookie_value)), time() + self::COOKIE_LIFETIME, "/", $_SERVER['HTTP_HOST'], true, true);
}
function process_cookie_json() {
if (!isset($_COOKIE[self::MY_COOKIE_NAME_JSON]))
return false;
$this->cookie_value = json_decode(base64_decode($_COOKIE[self::MY_COOKIE_NAME_JSON]), true);
setcookie(self::MY_COOKIE_NAME_JSON, '', -1, "/", $_SERVER['HTTP_HOST'], true, true);
unset($_COOKIE[self::MY_COOKIE_NAME_JSON]);
}
function filter_the_content_in_the_main_loop($content) {
if (!$this->cookie_value || !is_array($this->cookie_value))
return $content;
$alerts = [];
foreach ($this->cookie_value as $response_type => $messages)
$alerts[] = '<div class="alert alert-' . $response_type . '" role="alert">' . implode(PHP_EOL, $messages) . '</div>';
return implode(null, $alerts) . $content;
}
}
$my_custom_class = my_custom_class;
You can then set the cookie via:
my_custom_class::some_action_that_sets_the_cookie('the message');