What I did is combining cookies with transients just as others suggested. Be aware that the cookie must be sent with other HTTP headers, so init
must be called in the plugin registration area while read
and write
can be called later in the code, because they are database reads and writes. I use this code along with storage interfaces which store arrays or small collection of entities this way.
class TransientSessionIO implements IO{
protected $expirationSeconds;
protected $cookiePrefix;
public function __construct(array $settings = []){
$this->expirationSeconds = isset($settings['expiration_seconds'])?$settings['expiration_seconds']:600;
$this->cookiePrefix = isset($settings['cookie_prefix'])?$settings['cookie_prefix']:'transient_';
}
public function init(string $id){
$this->getKey($id);
}
public function read(string $id){
$data = get_transient($this->getKey($id));
if ($data !== false)
return $data;
}
public function write(string $id, array $data){
delete_transient($this->getKey($id));
set_transient($this->getKey($id), $data, $this->expirationSeconds);
}
protected $transientKey;
protected function getKey(string $id):string{
if (isset($this->transientKey))
return $this->transientKey;
$cookieKey = $this->cookiePrefix.$id;
if (isset($_COOKIE[$cookieKey]))
$this->transientKey = $_COOKIE[$cookieKey];
else {
$this->transientKey = $id.'__'.md5(''.time().rand());
setcookie($cookieKey, $this->transientKey, time() + $this->expirationSeconds);
}
return $this->transientKey;
}
}